Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1675 lines
47 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. qryparse.cxx
  5. Abstract:
  6. Author:
  7. Felix Wong [t-FelixW] 05-Nov-1996
  8. ++*/
  9. #include "nds.hxx"
  10. #pragma hdrstop
  11. //#define DEBUG_DUMPSTACK
  12. //#define DEBUG_DUMPRULE
  13. #if (defined(DEBUG_DUMPSTACK) || defined (DEBUG_DUMPRULE))
  14. #include "stdio.h"
  15. #endif
  16. #define MAPHEXTODIGIT(x) ( x >= '0' && x <= '9' ? (x-'0') : \
  17. x >= 'A' && x <= 'F' ? (x-'A'+10) : \
  18. x >= 'a' && x <= 'f' ? (x-'a'+10) : 0 )
  19. nuint16 g_MapTokenToNdsToken[] = {
  20. FTOK_END, // TOKEN_ERROR
  21. FTOK_LPAREN, // TOKEN_LPARAN
  22. FTOK_RPAREN, // TOKEN_RPARAN
  23. FTOK_OR, // TOKEN_OR
  24. FTOK_AND, // TOKEN_AND
  25. FTOK_NOT, // TOKEN_NOT
  26. FTOK_APPROX, // TOKEN_APPROX_EQ
  27. FTOK_EQ, // TOKEN_EQ
  28. FTOK_LE, // TOKEN_LE
  29. FTOK_GE, // TOKEN_GE
  30. FTOK_PRESENT, // TOKEN_PRESENT
  31. FTOK_ANAME, // TOKEN_ATTRTYPE
  32. FTOK_AVAL, // TOKEN_ATTRVAL
  33. FTOK_END // TOKEN_ENDINPUT
  34. };
  35. // Action Table
  36. typedef struct _action{
  37. DWORD type;
  38. DWORD dwState;
  39. }action;
  40. // Rule Table
  41. typedef struct _rule{
  42. DWORD dwNumber;
  43. DWORD dwA;
  44. }rule;
  45. enum types {
  46. N,
  47. S,
  48. R,
  49. A
  50. };
  51. #define X 99
  52. action g_action[28][14] = {
  53. // ERROR ,LPARAN,RPARAN,OR, AND, NOT, APPROX,EQ, LE, GE, PRESNT,ATYPE, VAL, END,
  54. /*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 } },
  55. /*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 } },
  56. /*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 } },
  57. /*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 } },
  58. /*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 } },
  59. /*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 } },
  60. /*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 } },
  61. /*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 } },
  62. /*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 } },
  63. /*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 } },
  64. /*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 } },
  65. /*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 } },
  66. /*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 } },
  67. /*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 } },
  68. /*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 } },
  69. /*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 } },
  70. /*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 } },
  71. /*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 } },
  72. /*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 } },
  73. /*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 } },
  74. /*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 } },
  75. /*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 } },
  76. /*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 } },
  77. /*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 } },
  78. /*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 } },
  79. /*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 } },
  80. /*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 } },
  81. /*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 } }
  82. };
  83. enum non_terminals {
  84. NONTERM_F,
  85. NONTERM_FC,
  86. NONTERM_AND,
  87. NONTERM_OR,
  88. NONTERM_NOT,
  89. NONTERM_FL,
  90. NONTERM_ITM,
  91. NONTERM_SMP,
  92. NONTERM_FT,
  93. NONTERM_PRS
  94. };
  95. rule g_rule[] = {
  96. // 1)No. of non-terminals and terminals on the right hand side
  97. // 2)The Parent
  98. /*00*/ {0, 0, },
  99. /*01*/ {3, NONTERM_F, },
  100. /*02*/ {1, NONTERM_FC, },
  101. /*03*/ {1, NONTERM_FC, },
  102. /*04*/ {1, NONTERM_FC, },
  103. /*05*/ {1, NONTERM_FC, },
  104. /*06*/ {2, NONTERM_AND, },
  105. /*07*/ {2, NONTERM_OR, },
  106. /*08*/ {2, NONTERM_NOT, },
  107. /*09*/ {1, NONTERM_FL, },
  108. /*10*/ {2, NONTERM_FL, },
  109. /*11*/ {1, NONTERM_ITM, },
  110. /*12*/ {1, NONTERM_ITM, },
  111. /*13*/ {1, NONTERM_ITM, },
  112. /*14*/ {3, NONTERM_SMP, },
  113. /*15*/ {1, NONTERM_FT, },
  114. /*16*/ {1, NONTERM_FT, },
  115. /*17*/ {1, NONTERM_FT, },
  116. /*18*/ {2, NONTERM_PRS, },
  117. /*19*/ {1, NONTERM_FT, }
  118. };
  119. #ifdef DEBUG_DUMPRULE
  120. LPWSTR g_rgszRule[] = {
  121. /*00*/ L"",
  122. /*01*/ L"F->(FC)",
  123. /*02*/ L"FC->AND",
  124. /*03*/ L"FC->OR",
  125. /*04*/ L"FC->NOT",
  126. /*05*/ L"FC->ITM",
  127. /*06*/ L"AND->&FL",
  128. /*07*/ L"OR->|FL",
  129. /*08*/ L"NOT->!F",
  130. /*09*/ L"FL->F",
  131. /*10*/ L"FL->F FL",
  132. /*11*/ L"ITM->SMP",
  133. /*12*/ L"ITM->PRS",
  134. /*13*/ L"ITM->STR",
  135. /*14*/ L"SMP->ATR FT VAL",
  136. /*15*/ L"FT->~=",
  137. /*16*/ L"FT->>=",
  138. /*17*/ L"FT-><=",
  139. /*18*/ L"PRS->ATR=*",
  140. /*19*/ L"FT->="
  141. };
  142. #endif
  143. DWORD g_goto[28][10] = {
  144. // F, FC, AND, OR, NOT, FL, ITM, SMP, FT, PRS,
  145. /*00*/ {1, X, X, X, X, X, X, X, X, X },
  146. /*01*/ {X, X, X, X, X, X, X, X, X, X },
  147. /*02*/ {X, 7, 3, 4, 5, X, 6, 8, X, 9 },
  148. /*03*/ {X, X, X, X, X, X, X, X, X, X },
  149. /*04*/ {X, X, X, X, X, X, X, X, X, X },
  150. /*05*/ {X, X, X, X, X, X, X, X, X, X },
  151. /*06*/ {X, X, X, X, X, X, X, X, X, X },
  152. /*07*/ {X, X, X, X, X, X, X, X, X, X },
  153. /*08*/ {X, X, X, X, X, X, X, X, X, X },
  154. /*09*/ {X, X, X, X, X, X, X, X, X, X },
  155. /*10*/ {X, X, X, X, X, X, X, X, X, X },
  156. /*11*/ {17, X, X, X, X, 16, X, X, X, X },
  157. /*12*/ {17, X, X, X, X, 18, X, X, X, X },
  158. /*13*/ {19, X, X, X, X, X, X, X, X, X },
  159. /*14*/ {X, X, X, X, X, X, X, X, 24, X },
  160. /*15*/ {X, X, X, X, X, X, X, X, X, X },
  161. /*16*/ {X, X, X, X, X, X, X, X, X, X },
  162. /*17*/ {17, X, X, X, X, 27, X, X, X, X },
  163. /*18*/ {X, X, X, X, X, X, X, X, X, X },
  164. /*19*/ {X, X, X, X, X, X, X, X, X, X },
  165. /*20*/ {X, X, X, X, X, X, X, X, X, X },
  166. /*21*/ {X, X, X, X, X, X, X, X, X, X },
  167. /*22*/ {X, X, X, X, X, X, X, X, X, X },
  168. /*23*/ {X, X, X, X, X, X, X, X, X, X },
  169. /*24*/ {X, X, X, X, X, X, X, X, X, X },
  170. /*25*/ {X, X, X, X, X, X, X, X, X, X },
  171. /*26*/ {X, X, X, X, X, X, X, X, X, X },
  172. /*27*/ {X, X, X, X, X, X, X, X, X, X }
  173. };
  174. HRESULT MapTokenToType(
  175. DWORD dwToken,
  176. DWORD *pdwType
  177. )
  178. {
  179. DWORD dwType;
  180. switch(dwToken) {
  181. case TOKEN_EQ:
  182. dwType = QUERY_EQUAL;
  183. break;
  184. case TOKEN_LE:
  185. dwType = QUERY_LE;
  186. break;
  187. case TOKEN_GE:
  188. dwType = QUERY_GE;
  189. break;
  190. case TOKEN_APPROX_EQ:
  191. dwType = QUERY_APPROX;
  192. break;
  193. default:
  194. return (E_ADS_INVALID_FILTER);
  195. }
  196. *pdwType = dwType;
  197. return (S_OK);
  198. }
  199. HRESULT Parse(
  200. LPWSTR szQuery,
  201. CQueryNode **ppNode,
  202. CAttrList **ppAttrList
  203. )
  204. {
  205. CStack Stack;
  206. CQryLexer Query(szQuery);
  207. LPWSTR lexeme;
  208. DWORD dwToken;
  209. DWORD dwState;
  210. HRESULT hr = E_ADS_INVALID_FILTER;
  211. CAttrList* pAttrList = new CAttrList;
  212. if (!pAttrList)
  213. return E_OUTOFMEMORY;
  214. CSyntaxNode *pSynNode = NULL;
  215. CQueryNode *pNode1 = NULL;
  216. CQueryNode *pNode2 = NULL;
  217. CQueryNode *pNode3 = NULL;
  218. // Push in State 0
  219. pSynNode = new CSyntaxNode;
  220. Stack.Push(pSynNode);
  221. pSynNode = NULL;
  222. #ifdef DEBUG_DUMPSTACK
  223. Stack.Dump();
  224. #endif
  225. while (1) {
  226. // Getting information for this iteration, dwToken and dwState
  227. hr = Query.GetCurrentToken(
  228. &lexeme,
  229. &dwToken
  230. );
  231. BAIL_ON_FAILURE(hr);
  232. hr = Stack.Current(&pSynNode);
  233. BAIL_ON_FAILURE(hr);
  234. dwState = pSynNode->_dwState;
  235. pSynNode = NULL;
  236. // Analysing and processing the data
  237. if (g_action[dwState][dwToken].type == S) {
  238. pSynNode = new CSyntaxNode;
  239. pSynNode->_dwState = g_action[dwState][dwToken].dwState;
  240. pSynNode->_dwToken = dwToken;
  241. switch (dwToken) {
  242. case TOKEN_ATTRTYPE:
  243. {
  244. hr = pAttrList->Add(lexeme);
  245. BAIL_ON_FAILURE(hr);
  246. }
  247. case TOKEN_ATTRVAL:
  248. // both TOKEN_ATTRTYPE and TOKEN_ATTRVAL will get here
  249. {
  250. LPWSTR szValue = AllocADsStr(lexeme);
  251. if (!szValue) {
  252. hr = E_OUTOFMEMORY;
  253. goto error;
  254. }
  255. pSynNode->SetNode(szValue);
  256. break;
  257. }
  258. }
  259. hr = Stack.Push(pSynNode);
  260. BAIL_ON_FAILURE(hr);
  261. pSynNode = NULL;
  262. hr = Query.GetNextToken(
  263. &lexeme,
  264. &dwToken
  265. );
  266. BAIL_ON_FAILURE(hr);
  267. #ifdef DEBUG_DUMPSTACK
  268. Stack.Dump();
  269. #endif
  270. }
  271. else if (g_action[dwState][dwToken].type == R) {
  272. DWORD dwRule = g_action[dwState][dwToken].dwState;
  273. DWORD dwNumber = g_rule[dwRule].dwNumber;
  274. #ifdef DEBUG_DUMPRULE
  275. wprintf(L"%s\n",g_rgszRule[dwRule]);
  276. #endif
  277. pSynNode = new CSyntaxNode;
  278. CSyntaxNode *pSynNodeRed;
  279. switch (dwRule) {
  280. case 1: // Reduction of Basic Filter rule
  281. {
  282. // Getting the middle node
  283. hr = Stack.Pop();
  284. BAIL_ON_FAILURE(hr);
  285. hr = Stack.Pop(&pSynNodeRed);
  286. BAIL_ON_FAILURE(hr);
  287. pSynNode->SetNode(
  288. pSynNodeRed->_pNode
  289. );
  290. pSynNodeRed->_dwType = SNODE_NULL;
  291. delete pSynNodeRed;
  292. hr = Stack.Pop();
  293. BAIL_ON_FAILURE(hr);
  294. break;
  295. }
  296. case 18: // Reduction of PRESENT rule
  297. {
  298. // Getting second node
  299. LPWSTR szType;
  300. hr = Stack.Pop();
  301. BAIL_ON_FAILURE(hr);
  302. hr = Stack.Pop(&pSynNodeRed);
  303. BAIL_ON_FAILURE(hr);
  304. szType = pSynNodeRed->_szValue;
  305. pSynNodeRed->_dwType = SNODE_NULL;
  306. delete pSynNodeRed;
  307. hr = MakeLeaf(
  308. szType,
  309. &pNode1
  310. );
  311. BAIL_ON_FAILURE(hr);
  312. hr = MakeNode(
  313. QUERY_PRESENT,
  314. pNode1,
  315. NULL,
  316. &pNode2
  317. );
  318. BAIL_ON_FAILURE(hr);
  319. pNode1 = NULL;
  320. pSynNode->SetNode(
  321. pNode2
  322. );
  323. pNode2 = NULL;
  324. break;
  325. }
  326. case 14: // Reduction of SMP rule
  327. {
  328. LPWSTR szType;
  329. LPWSTR szValue;
  330. DWORD dwType;
  331. DWORD dwToken;
  332. hr = Stack.Pop(&pSynNodeRed);
  333. BAIL_ON_FAILURE(hr);
  334. szValue = pSynNodeRed->_szValue;
  335. pSynNodeRed->_dwType = SNODE_NULL;
  336. delete pSynNodeRed;
  337. Stack.Pop(&pSynNodeRed);
  338. BAIL_ON_FAILURE(hr);
  339. dwToken = (DWORD)pSynNodeRed->_dwFilterType;
  340. pSynNodeRed->_dwType = SNODE_NULL;
  341. delete pSynNodeRed;
  342. hr = Stack.Pop(&pSynNodeRed);
  343. BAIL_ON_FAILURE(hr);
  344. szType = pSynNodeRed->_szValue;
  345. pSynNodeRed->_dwType = SNODE_NULL;
  346. delete pSynNodeRed;
  347. hr = MakeLeaf(
  348. szType,
  349. &pNode1
  350. );
  351. BAIL_ON_FAILURE(hr);
  352. hr = MakeLeaf(
  353. szValue,
  354. &pNode2
  355. );
  356. BAIL_ON_FAILURE(hr);
  357. hr = MapTokenToType(
  358. dwToken,
  359. &dwType
  360. );
  361. BAIL_ON_FAILURE(hr);
  362. hr = MakeNode(
  363. dwType,
  364. pNode1,
  365. pNode2,
  366. &pNode3
  367. );
  368. BAIL_ON_FAILURE(hr);
  369. pSynNode->SetNode(
  370. pNode3
  371. );
  372. pNode1 = NULL;
  373. pNode2 = NULL;
  374. pNode3 = NULL;
  375. break;
  376. }
  377. case 6: // Reduction of AND, OR rules
  378. case 7:
  379. {
  380. DWORD dwType;
  381. Stack.Pop(&pSynNodeRed);
  382. pSynNode->SetNode(
  383. pSynNodeRed->_pNode
  384. );
  385. pSynNodeRed->_dwType = SNODE_NULL;
  386. delete pSynNodeRed;
  387. Stack.Pop();
  388. // Adding in the type information
  389. if (dwRule == 6)
  390. dwType = QUERY_AND;
  391. else
  392. dwType = QUERY_OR;
  393. pSynNode->_pNode->_dwType = dwType;
  394. break;
  395. }
  396. case 10: // Reduction of FL rule
  397. {
  398. DWORD dwType;
  399. hr = Stack.Pop(&pSynNodeRed);
  400. BAIL_ON_FAILURE(hr);
  401. pNode2 = pSynNodeRed->_pNode;
  402. pSynNodeRed->_dwType = SNODE_NULL;
  403. delete pSynNodeRed;
  404. hr = Stack.Pop(&pSynNodeRed);
  405. BAIL_ON_FAILURE(hr);
  406. pNode1 = pSynNodeRed->_pNode;
  407. pSynNodeRed->_dwType = SNODE_NULL;
  408. delete pSynNodeRed;
  409. if (pNode2->_dwType == QUERY_UNKNOWN) {
  410. // It's not new node, append to node1
  411. hr = pNode2->AddChild(pNode1);
  412. BAIL_ON_FAILURE(hr);
  413. pSynNode->SetNode(
  414. pNode2
  415. );
  416. pNode1 = NULL;
  417. pNode2 = NULL;
  418. }
  419. else {
  420. // New node
  421. hr = MakeNode(
  422. QUERY_UNKNOWN,
  423. pNode1,
  424. pNode2,
  425. &pNode3
  426. );
  427. BAIL_ON_FAILURE(hr);
  428. pSynNode->SetNode(
  429. pNode3
  430. );
  431. pNode1 = NULL;
  432. pNode2 = NULL;
  433. pNode3 = NULL;
  434. }
  435. break;
  436. }
  437. case 9: // Reduction of FL rule
  438. {
  439. DWORD dwType;
  440. hr = Stack.Pop(&pSynNodeRed);
  441. BAIL_ON_FAILURE(hr);
  442. pNode1 = pSynNodeRed->_pNode;
  443. pSynNodeRed->_dwType = SNODE_NULL;
  444. delete pSynNodeRed;
  445. hr = MakeNode(
  446. QUERY_UNKNOWN,
  447. pNode1,
  448. NULL,
  449. &pNode3
  450. );
  451. BAIL_ON_FAILURE(hr);
  452. pSynNode->SetNode(
  453. pNode3
  454. );
  455. pNode1 = NULL;
  456. pNode3 = NULL;
  457. break;
  458. }
  459. case 8: // Reduction of NOT rule
  460. {
  461. Stack.Pop(&pSynNodeRed);
  462. pNode1 = pSynNodeRed->_pNode;
  463. pSynNodeRed->_dwType = SNODE_NULL;
  464. delete pSynNodeRed;
  465. hr = MakeNode(
  466. QUERY_NOT,
  467. pNode1,
  468. NULL,
  469. &pNode2
  470. );
  471. BAIL_ON_FAILURE(hr);
  472. pNode1 = NULL;
  473. hr = Stack.Pop();
  474. BAIL_ON_FAILURE(hr);
  475. pSynNode->SetNode(
  476. pNode2
  477. );
  478. pNode2 = NULL;
  479. break;
  480. }
  481. case 15: // Reduction of FT rule
  482. case 16:
  483. case 17:
  484. case 19:
  485. {
  486. // Propagating the last entry
  487. hr = Stack.Pop(&pSynNodeRed);
  488. BAIL_ON_FAILURE(hr);
  489. pSynNode->SetNode(
  490. pSynNodeRed->_dwToken
  491. );
  492. pSynNodeRed->_dwType = SNODE_NULL;
  493. delete pSynNodeRed;
  494. break;
  495. }
  496. default:
  497. {
  498. // For all the other rules, we propogate the last entry
  499. hr = Stack.Pop(&pSynNodeRed);
  500. BAIL_ON_FAILURE(hr);
  501. pSynNode->SetNode(
  502. pSynNodeRed->_pNode
  503. );
  504. pSynNodeRed->_dwType = SNODE_NULL;
  505. delete pSynNodeRed;
  506. for (DWORD i = 0;i<dwNumber-1;i++)
  507. Stack.Pop();
  508. }
  509. }
  510. hr = Stack.Current(&pSynNodeRed);
  511. BAIL_ON_FAILURE(hr);
  512. dwState = pSynNodeRed->_dwState;
  513. DWORD A = g_rule[dwRule].dwA;
  514. pSynNode->_dwState = g_goto[dwState][A];
  515. pSynNode->_dwToken = A;
  516. hr = Stack.Push(pSynNode);
  517. BAIL_ON_FAILURE(hr);
  518. pSynNode = NULL;
  519. #ifdef DEBUG_DUMPSTACK
  520. Stack.Dump();
  521. #endif
  522. }
  523. else if (g_action[dwState][dwToken].type == A){
  524. hr = Stack.Pop(&pSynNode);
  525. BAIL_ON_FAILURE(hr);
  526. *ppNode = pSynNode->_pNode;
  527. *ppAttrList = pAttrList;
  528. pSynNode->_dwType = SNODE_NULL;
  529. delete pSynNode;
  530. return S_OK;
  531. }
  532. else {
  533. hr = E_ADS_INVALID_FILTER;
  534. goto error;
  535. }
  536. }
  537. error:
  538. if (pAttrList) {
  539. delete pAttrList;
  540. }
  541. if (pSynNode) {
  542. delete pSynNode;
  543. }
  544. if (pNode1) {
  545. delete pNode1;
  546. }
  547. if (pNode2) {
  548. delete pNode2;
  549. }
  550. if (pNode3) {
  551. delete pNode3;
  552. }
  553. return hr;
  554. }
  555. CStack::CStack()
  556. {
  557. _dwStackIndex = 0;
  558. }
  559. CStack::~CStack()
  560. {
  561. DWORD dwIndex = _dwStackIndex;
  562. while (dwIndex > 0) {
  563. CSyntaxNode *pNode;
  564. pNode = _Stack[--dwIndex];
  565. delete pNode;
  566. }
  567. }
  568. #ifdef DEBUG_DUMPSTACK
  569. void CStack::Dump()
  570. {
  571. DWORD dwIndex = _dwStackIndex;
  572. printf("Stack:\n");
  573. while (dwIndex > 0) {
  574. CSyntaxNode *pNode;
  575. pNode = _Stack[--dwIndex];
  576. printf(
  577. "State=%5.0d, Token=%5.0d\n",
  578. pNode->_dwState,
  579. pNode->_dwToken
  580. );
  581. }
  582. }
  583. #endif
  584. HRESULT CStack::Push(CSyntaxNode* pNode)
  585. {
  586. if (_dwStackIndex < MAXVAL) {
  587. _Stack[_dwStackIndex++] = pNode;
  588. return S_OK;
  589. }
  590. else
  591. return E_FAIL;
  592. }
  593. HRESULT CStack::Pop(CSyntaxNode** ppNode)
  594. {
  595. if (_dwStackIndex > 0) {
  596. *ppNode = _Stack[--_dwStackIndex];
  597. return S_OK;
  598. }
  599. else {
  600. return E_FAIL;
  601. }
  602. }
  603. HRESULT CStack::Pop()
  604. {
  605. if (_dwStackIndex > 0) {
  606. CSyntaxNode *pNode;
  607. pNode = _Stack[--_dwStackIndex];
  608. delete pNode;
  609. return S_OK;
  610. }
  611. else {
  612. return E_FAIL;
  613. }
  614. }
  615. HRESULT CStack::Current(CSyntaxNode **ppNode)
  616. {
  617. if (_dwStackIndex > 0) {
  618. *ppNode = _Stack[_dwStackIndex-1];
  619. return S_OK;
  620. }
  621. else {
  622. return E_FAIL;
  623. }
  624. }
  625. CAttrList::CAttrList()
  626. {
  627. _rgAttr = NULL;
  628. _dwAttrCur = 0;
  629. }
  630. CAttrList::~CAttrList()
  631. {
  632. if (_rgAttr) {
  633. for (DWORD i=0;i<_dwAttrCur;i++)
  634. FreeADsStr(_rgAttr[i].szName);
  635. FreeADsMem(_rgAttr);
  636. }
  637. }
  638. HRESULT CAttrList::Add(LPWSTR szName)
  639. {
  640. HRESULT hr = S_OK;
  641. BOOL fBinary = FALSE;
  642. LPWSTR pszTemp = NULL;
  643. for (DWORD i=0;i<_dwAttrCur;i++) {
  644. if (_wcsicmp(
  645. szName,
  646. _rgAttr[i].szName
  647. ) == 0)
  648. break;
  649. }
  650. if (i != _dwAttrCur) // does not loop till the end, entry exist already
  651. return S_OK;
  652. LPWSTR szAttr = AllocADsStr(szName);
  653. if (!szAttr)
  654. return E_OUTOFMEMORY;
  655. //
  656. // Check if the attribute comes with a ";binary" specifier. This means
  657. // that the value has to be converted from the encoded form to
  658. // octet strings
  659. if (pszTemp = wcschr (szAttr, L';')) {
  660. //
  661. // Make sure binary appears at the end of the attribute name and
  662. // immediately after ;
  663. //
  664. if (_wcsicmp(pszTemp+1, L"binary") == 0) {
  665. fBinary = TRUE;
  666. //
  667. // Strip off the binary specifier.
  668. //
  669. wcstok(szAttr, L";");
  670. }
  671. }
  672. if (_dwAttrCur == _dwAttrMax) {
  673. if (!_rgAttr) {
  674. _rgAttr = (AttrNode*)AllocADsMem(ATTRNODE_INITIAL*sizeof(AttrNode));
  675. if (!_rgAttr) {
  676. hr = E_OUTOFMEMORY;
  677. goto error;
  678. }
  679. _dwAttrMax = ATTRNODE_INITIAL;
  680. }
  681. else {
  682. _rgAttr = (AttrNode*)ReallocADsMem(
  683. (void*)_rgAttr,
  684. _dwAttrMax*sizeof(AttrNode),
  685. (_dwAttrMax+ATTRNODE_INC)*sizeof(AttrNode)
  686. );
  687. if (!_rgAttr) {
  688. hr = E_OUTOFMEMORY;
  689. goto error;
  690. }
  691. _dwAttrMax+= ATTRNODE_INC;
  692. }
  693. }
  694. _rgAttr[_dwAttrCur].szName = szAttr;
  695. _rgAttr[_dwAttrCur].dwType = 0; //UNKNOWN at this point
  696. _rgAttr[_dwAttrCur].fBinary = fBinary;
  697. _dwAttrCur++;
  698. return S_OK;
  699. error:
  700. if (szAttr)
  701. FreeADsStr(szAttr);
  702. return (hr);
  703. }
  704. HRESULT CAttrList::SetupType(NDS_CONTEXT_HANDLE hADsContext)
  705. {
  706. DWORD dwStatus;
  707. HRESULT hr = S_OK;
  708. DWORD dwNumberOfEntries;
  709. DWORD dwInfoType;
  710. LPNDS_ATTR_DEF lpAttrDefs = NULL;
  711. DWORD i,j,k;
  712. LPWSTR *ppszAttrs = NULL;
  713. HANDLE hOperationData = NULL;
  714. if (_dwAttrCur == 0) {
  715. RRETURN(S_OK);
  716. }
  717. ppszAttrs = (LPWSTR *) AllocADsMem(_dwAttrCur * sizeof(LPWSTR *));
  718. if (!ppszAttrs) {
  719. BAIL_ON_FAILURE(E_OUTOFMEMORY);
  720. }
  721. for (i=0, j=0; i<_dwAttrCur; i++) {
  722. ppszAttrs[j++] = _rgAttr[i].szName;
  723. }
  724. hr = ADsNdsReadAttrDef(
  725. hADsContext,
  726. DS_ATTR_DEFS,
  727. ppszAttrs,
  728. _dwAttrCur,
  729. &hOperationData
  730. );
  731. BAIL_ON_FAILURE(hr);
  732. hr = ADsNdsGetAttrDefListFromBuffer(
  733. hADsContext,
  734. hOperationData,
  735. &dwNumberOfEntries,
  736. &dwInfoType,
  737. &lpAttrDefs
  738. );
  739. BAIL_ON_FAILURE(hr);
  740. if (dwNumberOfEntries != _dwAttrCur) {
  741. hr = E_ADS_INVALID_FILTER;
  742. goto error;
  743. }
  744. for (j = 0; j < dwNumberOfEntries ; j++ ) {
  745. for (k = 0; k < dwNumberOfEntries; k++) {
  746. if (_wcsicmp(
  747. _rgAttr[k].szName,
  748. lpAttrDefs[j].szAttributeName
  749. ) == 0) {
  750. _rgAttr[k].dwType = lpAttrDefs[j].dwSyntaxID;
  751. break;
  752. }
  753. }
  754. if (k == dwNumberOfEntries) // cannot find entry
  755. goto error;
  756. }
  757. error:
  758. if (ppszAttrs)
  759. FreeADsMem(ppszAttrs);
  760. if (hOperationData)
  761. ADsNdsFreeBuffer( hOperationData );
  762. ADsNdsFreeAttrDefList(lpAttrDefs, dwNumberOfEntries);
  763. RRETURN(hr);
  764. }
  765. HRESULT CAttrList::GetType(LPWSTR szName, DWORD *pdwType)
  766. {
  767. DWORD i = 0;
  768. for (i=0;i<_dwAttrCur;i++) {
  769. if (_wcsicmp(
  770. szName,
  771. _rgAttr[i].szName
  772. ) == 0)
  773. break;
  774. }
  775. if (i == _dwAttrCur) // Cannot find attribute
  776. return E_FAIL;
  777. *pdwType = _rgAttr[i].dwType;
  778. return S_OK;
  779. }
  780. CSyntaxNode::CSyntaxNode()
  781. {
  782. _dwType = SNODE_NULL;
  783. _dwToken = 0;
  784. _dwState = 0;
  785. _pNode = 0;
  786. }
  787. CSyntaxNode::~CSyntaxNode()
  788. {
  789. switch (_dwType) {
  790. case SNODE_SZ:
  791. FreeADsStr(_szValue);
  792. break;
  793. case SNODE_NODE:
  794. delete _pNode;
  795. break;
  796. default:
  797. break;
  798. }
  799. }
  800. void CSyntaxNode::SetNode(
  801. CQueryNode *pNode
  802. )
  803. {
  804. _pNode = pNode;
  805. _dwType = SNODE_NODE;
  806. }
  807. void CSyntaxNode::SetNode(
  808. LPWSTR szValue
  809. )
  810. {
  811. _szValue = szValue;
  812. _dwType = SNODE_SZ;
  813. }
  814. void CSyntaxNode::SetNode(
  815. DWORD dwFilterType
  816. )
  817. {
  818. _dwFilterType = dwFilterType;
  819. _dwType = SNODE_FILTER;
  820. }
  821. //+---------------------------------------------------------------------------
  822. //
  823. // Function: CQueryNode::CQueryNode
  824. //
  825. // Synopsis: Constructor of the CQueryNode
  826. //
  827. // Arguments:
  828. //
  829. // Returns:
  830. //
  831. // Modifies:
  832. //
  833. // History: 11-12-96 Felix Wong Created.
  834. //
  835. //----------------------------------------------------------------------------
  836. CQueryNode::CQueryNode()
  837. {
  838. _dwType = 0;
  839. _szValue = NULL;
  840. _dwQueryNode = 0;
  841. _rgQueryNode = NULL;
  842. _dwQueryNodeMax = 0;
  843. }
  844. //+---------------------------------------------------------------------------
  845. //
  846. // Function: CQueryNode::SetToString
  847. //
  848. // Synopsis: Set the Node to be a String Node
  849. //
  850. // Arguments: szValue value of the string
  851. //
  852. // Returns:
  853. //
  854. // Modifies:
  855. //
  856. // History: 11-12-96 Felix Wong Created.
  857. //
  858. //----------------------------------------------------------------------------
  859. HRESULT CQueryNode::SetToString(
  860. LPWSTR szValue
  861. )
  862. {
  863. _szValue = szValue;
  864. /*
  865. _szValue = AllocADsStr(szValue);
  866. if (!_szValue) {
  867. return E_OUTOFMEMORY;
  868. }
  869. */
  870. _dwType = QUERY_STRING;
  871. return S_OK;
  872. }
  873. //+---------------------------------------------------------------------------
  874. //
  875. // Function: CQueryNode::~CQueryNode
  876. //
  877. // Synopsis: Destructor of the CQueryNode
  878. //
  879. // Arguments:
  880. //
  881. // Returns:
  882. //
  883. // Modifies:
  884. //
  885. // History: 11-12-96 Felix Wong Created.
  886. //
  887. //----------------------------------------------------------------------------
  888. CQueryNode::~CQueryNode()
  889. {
  890. if (_szValue)
  891. FreeADsStr(_szValue);
  892. if (_rgQueryNode) {
  893. for (DWORD i=0;i<_dwQueryNode;i++) {
  894. delete _rgQueryNode[i];
  895. }
  896. FreeADsMem(_rgQueryNode);
  897. }
  898. }
  899. //+---------------------------------------------------------------------------
  900. //
  901. // Function: CQueryNode::AddChild
  902. //
  903. // Synopsis: Add a child to the node
  904. //
  905. // Arguments: CQueryNode *pChild pointer to the child to be added
  906. //
  907. // Returns:
  908. //
  909. // Modifies:
  910. //
  911. // History: 11-12-96 Felix Wong Created.
  912. //
  913. //----------------------------------------------------------------------------
  914. HRESULT CQueryNode::AddChild(CQueryNode *pChild)
  915. {
  916. if (_dwQueryNode == _dwQueryNodeMax) {
  917. if (!_rgQueryNode) {
  918. _rgQueryNode = (CQueryNode**)AllocADsMem(QUERYNODE_INITIAL*sizeof(CQueryNode*));
  919. if (!_rgQueryNode) {
  920. return E_OUTOFMEMORY;
  921. }
  922. _dwQueryNodeMax = QUERYNODE_INITIAL;
  923. }
  924. else {
  925. _rgQueryNode = (CQueryNode**)ReallocADsMem(
  926. (void*)_rgQueryNode,
  927. _dwQueryNodeMax*sizeof(CQueryNode*),
  928. (_dwQueryNodeMax+QUERYNODE_INC)*sizeof(CQueryNode*)
  929. );
  930. if (!_rgQueryNode) {
  931. return E_OUTOFMEMORY;
  932. }
  933. _dwQueryNodeMax+= QUERYNODE_INC;
  934. }
  935. }
  936. _rgQueryNode[_dwQueryNode] = pChild;
  937. _dwQueryNode++;
  938. return S_OK;
  939. }
  940. HRESULT CQueryNode::AddToFilterBuf(
  941. pFilter_Cursor_T pCur,
  942. CAttrList *pAttrList
  943. )
  944. {
  945. HRESULT hr = E_FAIL;
  946. nuint16 luTokenType;
  947. DWORD dwStatus = 0;
  948. LPWSTR szValue = NULL;
  949. LPWSTR szAttr = NULL;
  950. NWDSCCODE ccode;
  951. void* pValue = NULL;
  952. // Looking at type of operation
  953. switch (_dwType) {
  954. case QUERY_EQUAL:
  955. case QUERY_LE:
  956. case QUERY_GE:
  957. case QUERY_APPROX:
  958. case QUERY_PRESENT:
  959. {
  960. DWORD dwSyntax;
  961. DWORD dwAttrType;
  962. LPWSTR pszTemp = NULL;
  963. // Getting left node
  964. if (_rgQueryNode[0] &&
  965. _rgQueryNode[0]->_dwType == QUERY_STRING) {
  966. szAttr = AllocADsStr(_rgQueryNode[0]->_szValue);
  967. if (!szAttr) {
  968. hr = E_OUTOFMEMORY;
  969. goto error;
  970. }
  971. }
  972. else {
  973. // No nodes available
  974. goto error;
  975. }
  976. // Get syntax info of right node from attribute list
  977. hr = pAttrList->GetType(
  978. szAttr,
  979. &dwAttrType
  980. );
  981. BAIL_ON_FAILURE(hr);
  982. // Getting right node
  983. if (_rgQueryNode[1] &&
  984. _rgQueryNode[1]->_dwType == QUERY_STRING) {
  985. // Format the node depending on the syntax
  986. switch (dwAttrType) {
  987. // WIDE STRING
  988. case 1:
  989. case 2:
  990. case 3:
  991. case 4:
  992. case 5:
  993. case 10:
  994. case 11:
  995. case 20:
  996. pValue = (void *) AllocADsStr(_rgQueryNode[1]->_szValue);
  997. if (!pValue) {
  998. hr = E_OUTOFMEMORY;
  999. goto error;
  1000. }
  1001. break;
  1002. // BOOLEAN
  1003. case 7: {
  1004. Boolean_T *pBool = (Boolean_T *) AllocADsMem(sizeof(Boolean_T));
  1005. if (!pBool) {
  1006. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1007. }
  1008. *pBool = (Boolean_T) _wtol(_rgQueryNode[1]->_szValue);
  1009. pValue = pBool;
  1010. break;
  1011. }
  1012. // Binary Strings
  1013. case 9: {
  1014. hr = E_ADS_CANT_CONVERT_DATATYPE;
  1015. goto error;
  1016. break;
  1017. }
  1018. // DWORD
  1019. case 8 :
  1020. case 22 :
  1021. case 27 : {
  1022. Integer_T *pInteger = (Integer_T *) AllocADsMem(sizeof(Integer_T));
  1023. if (!pInteger) {
  1024. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1025. }
  1026. *pInteger = (Integer_T) _wtol(_rgQueryNode[1]->_szValue);
  1027. pValue = pInteger;
  1028. break;
  1029. }
  1030. case 6 :
  1031. case 13 :
  1032. case 14 :
  1033. case 15 :
  1034. case 16 :
  1035. case 17 :
  1036. case 18 :
  1037. case 19 :
  1038. case 23 :
  1039. case 24 :
  1040. case 25 :
  1041. case 26 :
  1042. default:
  1043. hr = E_ADS_CANT_CONVERT_DATATYPE;
  1044. goto error;
  1045. break;
  1046. }
  1047. }
  1048. hr = MapQueryToNDSType(
  1049. _dwType,
  1050. &luTokenType
  1051. );
  1052. BAIL_ON_FAILURE (hr);
  1053. ccode = NWDSAddFilterToken(
  1054. pCur,
  1055. FTOK_LPAREN,
  1056. NULL,
  1057. 0
  1058. );
  1059. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1060. if (_dwType == QUERY_PRESENT ) {
  1061. //
  1062. // First add the present token and then the attribute
  1063. //
  1064. ccode = NWDSAddFilterToken(
  1065. pCur,
  1066. FTOK_PRESENT,
  1067. NULL,
  1068. 0
  1069. );
  1070. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1071. ccode = NWDSAddFilterToken(
  1072. pCur,
  1073. FTOK_ANAME,
  1074. szAttr,
  1075. dwAttrType
  1076. );
  1077. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1078. ccode = NWDSAddFilterToken(
  1079. pCur,
  1080. FTOK_RPAREN,
  1081. NULL,
  1082. 0
  1083. );
  1084. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1085. }
  1086. else {
  1087. // All the rest are binary operators. Add the attribute name,
  1088. // operator and then the attribute value
  1089. //
  1090. ccode = NWDSAddFilterToken(
  1091. pCur,
  1092. FTOK_ANAME,
  1093. szAttr,
  1094. dwAttrType
  1095. );
  1096. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1097. ccode = NWDSAddFilterToken(
  1098. pCur,
  1099. luTokenType,
  1100. NULL,
  1101. 0
  1102. );
  1103. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1104. ccode = NWDSAddFilterToken(
  1105. pCur,
  1106. FTOK_AVAL,
  1107. pValue,
  1108. dwAttrType
  1109. );
  1110. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1111. ccode = NWDSAddFilterToken(
  1112. pCur,
  1113. FTOK_RPAREN,
  1114. NULL,
  1115. 0
  1116. );
  1117. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1118. }
  1119. break;
  1120. }
  1121. case QUERY_AND:
  1122. case QUERY_OR:
  1123. {
  1124. hr = MapQueryToNDSType(
  1125. _dwType,
  1126. &luTokenType
  1127. );
  1128. BAIL_ON_FAILURE (hr);
  1129. // Create first node
  1130. if (!_rgQueryNode[0])
  1131. goto error;
  1132. ccode = NWDSAddFilterToken(
  1133. pCur,
  1134. FTOK_LPAREN,
  1135. NULL,
  1136. 0
  1137. );
  1138. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1139. hr = _rgQueryNode[0]->AddToFilterBuf(
  1140. pCur,
  1141. pAttrList
  1142. );
  1143. BAIL_ON_FAILURE (hr);
  1144. // Go through a loop creating the rest
  1145. for (DWORD i=1;i<_dwQueryNode;i++) {
  1146. if (!_rgQueryNode[i])
  1147. goto error;
  1148. ccode = NWDSAddFilterToken(
  1149. pCur,
  1150. luTokenType,
  1151. NULL,
  1152. 0
  1153. );
  1154. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1155. hr = _rgQueryNode[i]->AddToFilterBuf(
  1156. pCur,
  1157. pAttrList
  1158. );
  1159. BAIL_ON_FAILURE (hr);
  1160. }
  1161. ccode = NWDSAddFilterToken(
  1162. pCur,
  1163. FTOK_RPAREN,
  1164. NULL,
  1165. 0
  1166. );
  1167. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1168. break;
  1169. }
  1170. case QUERY_NOT:
  1171. {
  1172. hr = MapQueryToNDSType(
  1173. _dwType,
  1174. &luTokenType
  1175. );
  1176. BAIL_ON_FAILURE (hr);
  1177. // Create first node
  1178. if (!_rgQueryNode[0])
  1179. goto error;
  1180. ccode = NWDSAddFilterToken(
  1181. pCur,
  1182. FTOK_LPAREN,
  1183. NULL,
  1184. 0
  1185. );
  1186. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1187. ccode = NWDSAddFilterToken(
  1188. pCur,
  1189. FTOK_NOT,
  1190. NULL,
  1191. 0
  1192. );
  1193. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1194. hr = _rgQueryNode[0]->AddToFilterBuf(
  1195. pCur,
  1196. pAttrList
  1197. );
  1198. BAIL_ON_FAILURE (hr);
  1199. ccode = NWDSAddFilterToken(
  1200. pCur,
  1201. FTOK_RPAREN,
  1202. NULL,
  1203. 0
  1204. );
  1205. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1206. break;
  1207. }
  1208. default:
  1209. goto error;
  1210. }
  1211. RRETURN(hr);
  1212. error:
  1213. if (szAttr)
  1214. FreeADsStr(szAttr);
  1215. if (pValue)
  1216. FreeADsMem(pValue);
  1217. return hr;
  1218. }
  1219. //+---------------------------------------------------------------------------
  1220. //
  1221. // Function: CQueryNode::FreeFilterTokens
  1222. //
  1223. // Synopsis: Frees dynamically-allocated attributes passed to
  1224. // NWDSAddFilterToken by CQueryNode::AddToFilterBuffer
  1225. //
  1226. // Arguments: syntax NetWare syntax attribute ID
  1227. // val ptr. to memory to be freed
  1228. //
  1229. // Returns:
  1230. //
  1231. // Modifies: deallocates the memory
  1232. //
  1233. // History: 9-18-99 Matthew Rimer Created.
  1234. //
  1235. //----------------------------------------------------------------------------
  1236. void N_FAR N_CDECL CQueryNode::FreeFilterTokens(
  1237. nuint32 syntax,
  1238. nptr pVal
  1239. )
  1240. {
  1241. if (pVal) {
  1242. switch(syntax) {
  1243. // WIDE STRING
  1244. case 1:
  1245. case 2:
  1246. case 3:
  1247. case 4:
  1248. case 5:
  1249. case 10:
  1250. case 11:
  1251. case 20:
  1252. FreeADsStr((LPWSTR) pVal);
  1253. break;
  1254. // BOOLEAN
  1255. case 7:
  1256. FreeADsMem(pVal);
  1257. break;
  1258. // DWORD
  1259. case 8:
  1260. case 22:
  1261. case 27:
  1262. FreeADsMem(pVal);
  1263. break;
  1264. // attribute name
  1265. case -1:
  1266. FreeADsStr((LPWSTR) pVal);
  1267. break;
  1268. default:
  1269. break;
  1270. }
  1271. }
  1272. }
  1273. //+---------------------------------------------------------------------------
  1274. //
  1275. // Function: CQueryNode::MapQueryToNDSType
  1276. //
  1277. // Synopsis: Maps the node type to the equivalent NDS types
  1278. //
  1279. // Arguments: dwType input type
  1280. // pdwNDSType output type
  1281. //
  1282. // Returns:
  1283. //
  1284. // Modifies:
  1285. //
  1286. // History: 11-12-96 Felix Wong Created.
  1287. //
  1288. //----------------------------------------------------------------------------
  1289. HRESULT CQueryNode::MapQueryToNDSType(
  1290. DWORD dwType,
  1291. nuint16 *pulNDSTokenType
  1292. )
  1293. {
  1294. nuint16 ulNDSTokenType;
  1295. switch(dwType) {
  1296. case QUERY_EQUAL:
  1297. ulNDSTokenType = FTOK_EQ;
  1298. break;
  1299. case QUERY_LE:
  1300. ulNDSTokenType = FTOK_LE;
  1301. break;
  1302. case QUERY_GE:
  1303. ulNDSTokenType = FTOK_GE;
  1304. break;
  1305. case QUERY_APPROX:
  1306. ulNDSTokenType = FTOK_APPROX;
  1307. break;
  1308. case QUERY_PRESENT:
  1309. ulNDSTokenType = FTOK_PRESENT;
  1310. break;
  1311. case QUERY_NOT:
  1312. ulNDSTokenType = FTOK_NOT;
  1313. break;
  1314. case QUERY_AND:
  1315. ulNDSTokenType = FTOK_AND;
  1316. break;
  1317. case QUERY_OR:
  1318. ulNDSTokenType = FTOK_OR;
  1319. break;
  1320. default:
  1321. return (E_ADS_INVALID_FILTER);
  1322. }
  1323. *pulNDSTokenType = ulNDSTokenType;
  1324. return (S_OK);
  1325. }
  1326. // Helper Functions for creating nodes using the CQueryNode Class
  1327. //+---------------------------------------------------------------------------
  1328. //
  1329. // Function: MakeNode
  1330. //
  1331. // Synopsis: Make a node with the input values
  1332. //
  1333. // Arguments: dwType type of node
  1334. // pLQueryNode pointer to left node
  1335. // pRQueryNode pointer to right node
  1336. // ppQueryNodeReturn pointer to Return Node
  1337. //
  1338. // Returns:
  1339. //
  1340. // Modifies:
  1341. //
  1342. // History: 11-12-96 Felix Wong Created.
  1343. //
  1344. //----------------------------------------------------------------------------
  1345. HRESULT MakeNode(
  1346. DWORD dwType,
  1347. CQueryNode *pLQueryNode,
  1348. CQueryNode *pRQueryNode,
  1349. CQueryNode **ppQueryNodeReturn
  1350. )
  1351. {
  1352. HRESULT hr = S_OK;
  1353. CQueryNode *pQueryNode = new CQueryNode();
  1354. if (!pQueryNode)
  1355. return E_OUTOFMEMORY;
  1356. pQueryNode->_dwType = dwType;
  1357. hr = pQueryNode->AddChild(pLQueryNode);
  1358. BAIL_ON_FAILURE(hr);
  1359. if (pRQueryNode) {
  1360. pQueryNode->AddChild(pRQueryNode);
  1361. BAIL_ON_FAILURE(hr);
  1362. }
  1363. *ppQueryNodeReturn = pQueryNode;
  1364. RRETURN(hr);
  1365. error:
  1366. delete pQueryNode;
  1367. RRETURN(hr);
  1368. }
  1369. //+---------------------------------------------------------------------------
  1370. //
  1371. // Function: MakeLeaf
  1372. //
  1373. // Synopsis: Constructor of the CQueryNode
  1374. //
  1375. // Arguments: szValue value of the string
  1376. // ppQueryNodeReturn the return node
  1377. //
  1378. // Returns:
  1379. //
  1380. // Modifies:
  1381. //
  1382. // History: 11-12-96 Felix Wong Created.
  1383. //
  1384. //----------------------------------------------------------------------------
  1385. HRESULT MakeLeaf(
  1386. LPWSTR szValue,
  1387. CQueryNode **ppQueryNodeReturn
  1388. )
  1389. {
  1390. HRESULT hr = S_OK;
  1391. CQueryNode *pQueryNode = new CQueryNode();
  1392. if (!pQueryNode)
  1393. return E_OUTOFMEMORY;
  1394. hr = pQueryNode->SetToString(szValue);
  1395. BAIL_ON_FAILURE(hr);
  1396. *ppQueryNodeReturn = pQueryNode;
  1397. RRETURN(hr);
  1398. error:
  1399. delete pQueryNode;
  1400. RRETURN(hr);
  1401. }
  1402. HRESULT
  1403. AdsNdsGenerateFilterBuffer(
  1404. NDS_CONTEXT_HANDLE hADsContext,
  1405. LPWSTR szSearchFilter,
  1406. NDS_BUFFER_HANDLE *phFilterBuf
  1407. )
  1408. {
  1409. NWDSContextHandle context;
  1410. HRESULT hr = E_ADS_INVALID_FILTER;
  1411. NWDSCCODE ccode;
  1412. BOOL fBufAllocated = FALSE;
  1413. DWORD i, j;
  1414. pFilter_Cursor_T pCur;
  1415. NDS_BUFFER_HANDLE hFilterBuf = NULL;
  1416. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1417. PNDS_BUFFER_DATA pFilterBuf = (PNDS_BUFFER_DATA) hFilterBuf;
  1418. nuint16 luFilterToken;
  1419. CQueryNode *pNode = NULL;
  1420. CAttrList *pAttrList = NULL;
  1421. if (!hADsContext || !phFilterBuf) {
  1422. RRETURN (E_ADS_BAD_PARAMETER);
  1423. }
  1424. // Generate the parse tree and the attribute list
  1425. hr = Parse(
  1426. szSearchFilter,
  1427. &pNode,
  1428. &pAttrList
  1429. );
  1430. BAIL_ON_FAILURE(hr);
  1431. // Setup syntax information in the attribute list
  1432. hr = pAttrList->SetupType(hADsContext);
  1433. BAIL_ON_FAILURE(hr);
  1434. hr = ADsNdsCreateBuffer(
  1435. hADsContext,
  1436. DSV_SEARCH_FILTER,
  1437. &hFilterBuf
  1438. );
  1439. BAIL_ON_FAILURE(hr);
  1440. fBufAllocated = TRUE;
  1441. // Generate the parse tree and the attribute list
  1442. ccode = NWDSAllocFilter(&pCur);
  1443. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1444. // Generate the NDS tree
  1445. hr = pNode->AddToFilterBuf(
  1446. pCur,
  1447. pAttrList
  1448. );
  1449. BAIL_ON_FAILURE(hr);
  1450. hr = ADsNdsPutFilter(
  1451. hADsContext,
  1452. hFilterBuf,
  1453. pCur,
  1454. CQueryNode::FreeFilterTokens
  1455. );
  1456. BAIL_ON_FAILURE(hr);
  1457. *phFilterBuf = hFilterBuf;
  1458. if (pNode)
  1459. delete pNode;
  1460. if (pAttrList)
  1461. delete pAttrList;
  1462. RRETURN(S_OK);
  1463. error:
  1464. if (fBufAllocated) {
  1465. ADsNdsFreeBuffer(hFilterBuf);
  1466. }
  1467. return hr;
  1468. }