Leaked source code of windows server 2003
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.

547 lines
16 KiB

  1. //
  2. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  3. //
  4. #include "precomp.h"
  5. const WCHAR QueryConvertor::wchAND = L'&';
  6. const WCHAR QueryConvertor::wchOR = L'|';
  7. const WCHAR QueryConvertor::wchNOT = L'!';
  8. const WCHAR QueryConvertor::wchSTAR = L'*';
  9. const WCHAR QueryConvertor::wchEQUAL = L'=';
  10. const WCHAR QueryConvertor::wchLEFT_BRACKET = L'(';
  11. const WCHAR QueryConvertor::wchRIGHT_BRACKET = L')';
  12. const WCHAR QueryConvertor::wchBACK_SLASH = L'\\';
  13. LPCWSTR QueryConvertor::pszGE = L">=";
  14. LPCWSTR QueryConvertor::pszLE = L"<=";
  15. int Stack::s_iMax = 100;
  16. // This assumes that enough memory has been allocated to the resulting query
  17. BOOLEAN QueryConvertor::ConvertQueryToLDAP(SQL_LEVEL_1_RPN_EXPRESSION *pExp, LPWSTR pszLDAPQuery, int nLength)
  18. {
  19. Stack t_stack;
  20. int iCurrentOperator = 0, idwNumOperandsLeft = 0;
  21. int iOutputIndex = 0;
  22. if(pExp->nNumTokens == 0)
  23. return TRUE;
  24. int iCurrentToken = pExp->nNumTokens -1;
  25. SQL_LEVEL_1_TOKEN *pNextToken = pExp->pArrayOfTokens + iCurrentToken;
  26. BOOLEAN retVal = FALSE, done = FALSE;
  27. // Write a '(' at the head of the LDAP Query
  28. pszLDAPQuery[iOutputIndex ++] = wchLEFT_BRACKET;
  29. while (!done && iCurrentToken >= 0)
  30. {
  31. switch(pNextToken->nTokenType)
  32. {
  33. case SQL_LEVEL_1_TOKEN::OP_EXPRESSION:
  34. {
  35. // Try to tranlsate expression to LDAP
  36. if(TranslateExpression(pszLDAPQuery, &iOutputIndex, pNextToken->nOperator, pNextToken->pPropertyName, &pNextToken->vConstValue, nLength))
  37. {
  38. // If we've finished all the operands for the current operator, get the next one
  39. idwNumOperandsLeft --;
  40. while(idwNumOperandsLeft == 0)
  41. {
  42. pszLDAPQuery[iOutputIndex ++] = wchRIGHT_BRACKET;
  43. if(!t_stack.Pop(&iCurrentOperator, &idwNumOperandsLeft))
  44. done = TRUE;
  45. idwNumOperandsLeft --;
  46. }
  47. iCurrentToken --;
  48. }
  49. else
  50. done = TRUE;
  51. pNextToken --;
  52. break;
  53. }
  54. case SQL_LEVEL_1_TOKEN::TOKEN_AND:
  55. {
  56. if(iCurrentOperator)
  57. {
  58. if(!t_stack.Push(iCurrentOperator, idwNumOperandsLeft))
  59. done = TRUE;
  60. iCurrentOperator = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  61. idwNumOperandsLeft = 2;
  62. pszLDAPQuery[iOutputIndex ++] = wchLEFT_BRACKET;
  63. pszLDAPQuery[iOutputIndex ++] = wchAND;
  64. }
  65. else
  66. {
  67. pszLDAPQuery[iOutputIndex ++] = wchLEFT_BRACKET;
  68. pszLDAPQuery[iOutputIndex ++] = wchAND;
  69. iCurrentOperator = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  70. idwNumOperandsLeft = 2;
  71. }
  72. iCurrentToken --;
  73. pNextToken --;
  74. break;
  75. }
  76. case SQL_LEVEL_1_TOKEN::TOKEN_OR:
  77. {
  78. if(iCurrentOperator)
  79. {
  80. if(!t_stack.Push(iCurrentOperator, idwNumOperandsLeft))
  81. done = TRUE;
  82. iCurrentOperator = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  83. idwNumOperandsLeft = 2;
  84. pszLDAPQuery[iOutputIndex ++] = wchLEFT_BRACKET;
  85. pszLDAPQuery[iOutputIndex ++] = wchOR;
  86. }
  87. else
  88. {
  89. pszLDAPQuery[iOutputIndex ++] = wchLEFT_BRACKET;
  90. pszLDAPQuery[iOutputIndex ++] = wchOR;
  91. iCurrentOperator = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  92. idwNumOperandsLeft = 2;
  93. }
  94. iCurrentToken --;
  95. pNextToken --;
  96. break;
  97. }
  98. case SQL_LEVEL_1_TOKEN::TOKEN_NOT:
  99. {
  100. if(iCurrentOperator)
  101. {
  102. if(!t_stack.Push(iCurrentOperator, idwNumOperandsLeft))
  103. done = TRUE;
  104. iCurrentOperator = SQL_LEVEL_1_TOKEN::TOKEN_NOT;
  105. idwNumOperandsLeft = 1;
  106. pszLDAPQuery[iOutputIndex ++] = wchLEFT_BRACKET;
  107. pszLDAPQuery[iOutputIndex ++] = wchNOT;
  108. }
  109. else
  110. {
  111. pszLDAPQuery[iOutputIndex ++] = wchLEFT_BRACKET;
  112. pszLDAPQuery[iOutputIndex ++] = wchNOT;
  113. iCurrentOperator = SQL_LEVEL_1_TOKEN::TOKEN_NOT;
  114. idwNumOperandsLeft = 1;
  115. }
  116. iCurrentToken --;
  117. pNextToken --;
  118. break;
  119. }
  120. default:
  121. done = TRUE;
  122. break;
  123. }
  124. }
  125. // Check if we used up all the tokens
  126. if(iCurrentToken == -1)
  127. retVal = TRUE;
  128. // Write a ')' at the end of the LDAP Query
  129. pszLDAPQuery[iOutputIndex ++] = wchRIGHT_BRACKET;
  130. pszLDAPQuery[iOutputIndex ++] = NULL;
  131. return retVal;
  132. }
  133. BOOLEAN QueryConvertor::TranslateExpression(LPWSTR pszLDAPQuery, int *piOutputIndex,
  134. int iOperator, LPCWSTR pszPropertyName, VARIANT *pValue, int nLength)
  135. {
  136. // If it is a CIMOM System property, then dont attempt to map it to LDAP
  137. if(pszPropertyName[0] == L'_' &&
  138. pszPropertyName[1] == L'_' )
  139. return TRUE;
  140. // If it is ADSIPath, convert it to distinguishedName attribute
  141. if(_wcsicmp(pszPropertyName, ADSI_PATH_ATTR) == 0 )
  142. {
  143. if(pValue== NULL || pValue->vt == VT_NULL)
  144. {
  145. if(iOperator == SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL)
  146. {
  147. // Put the property name as DistiguishedName
  148. if((*piOutputIndex) + (int)wcslen(DISTINGUISHED_NAME_ATTR) < nLength ) {
  149. wcscpy(pszLDAPQuery + *piOutputIndex, DISTINGUISHED_NAME_ATTR);
  150. *piOutputIndex += wcslen(DISTINGUISHED_NAME_ATTR);
  151. }else return FALSE;
  152. if(*piOutputIndex + 2 < nLength){
  153. *(pszLDAPQuery + *piOutputIndex) = wchEQUAL;
  154. (*piOutputIndex) ++;
  155. *(pszLDAPQuery + *piOutputIndex) = wchSTAR;
  156. (*piOutputIndex) ++;
  157. }else return FALSE;
  158. return TRUE;
  159. }
  160. else
  161. {
  162. // The '!'
  163. if(*piOutputIndex + 1 < nLength){
  164. *(pszLDAPQuery + *piOutputIndex) = wchNOT;
  165. (*piOutputIndex) ++;
  166. }else return FALSE;
  167. // The '('
  168. if(*piOutputIndex + 1 < nLength){
  169. *(pszLDAPQuery + *piOutputIndex) = wchLEFT_BRACKET;
  170. (*piOutputIndex) ++;
  171. }else return FALSE;
  172. if(TranslateExpression(pszLDAPQuery, piOutputIndex, SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL, pszPropertyName, NULL, nLength))
  173. {
  174. // The ')'
  175. if(*piOutputIndex + 1 < nLength){
  176. *(pszLDAPQuery + *piOutputIndex) = wchRIGHT_BRACKET;
  177. (*piOutputIndex) ++;
  178. }else return FALSE;
  179. return TRUE;
  180. }
  181. else
  182. return FALSE;
  183. }
  184. }
  185. // TODO - WinMgmt should not allow this. It should check that the property type matches the property value
  186. // As soon as Winmgmt has fixed this bug, the next 2 lines may be deleted
  187. if(pValue->vt != VT_BSTR)
  188. return FALSE;
  189. // Get the parentADSI path and RDN from the ADSI Path
  190. IADsPathname *pADsPathName = NULL;
  191. BSTR strADSIPath = SysAllocString(pValue->bstrVal);
  192. BSTR strDN = NULL;
  193. BOOLEAN bRetVal = FALSE;
  194. HRESULT result = E_FAIL;
  195. if(SUCCEEDED(result = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_ALL, IID_IADsPathname, (LPVOID *)&pADsPathName)))
  196. {
  197. if(SUCCEEDED(result = pADsPathName->Set(strADSIPath, ADS_SETTYPE_FULL)))
  198. {
  199. // This gives the DN
  200. if(SUCCEEDED(result = pADsPathName->Retrieve(ADS_FORMAT_X500_DN, &strDN)))
  201. {
  202. // Put the property name as DistiguishedName
  203. if(*piOutputIndex + (int)wcslen(DISTINGUISHED_NAME_ATTR) < nLength){
  204. wcscpy(pszLDAPQuery + *piOutputIndex, DISTINGUISHED_NAME_ATTR);
  205. *piOutputIndex += wcslen(DISTINGUISHED_NAME_ATTR);
  206. }else return FALSE;
  207. // Put the LDAP Operator
  208. if(iOperator == SQL_LEVEL_1_TOKEN::OP_EQUAL)
  209. {
  210. if(*piOutputIndex + 1 < nLength){
  211. *(pszLDAPQuery + *piOutputIndex) = wchEQUAL;
  212. (*piOutputIndex) ++;
  213. }else return FALSE;
  214. }
  215. else
  216. {
  217. // The '!'
  218. if(*piOutputIndex + 2 < nLength){
  219. *(pszLDAPQuery + *piOutputIndex) = wchNOT;
  220. (*piOutputIndex) ++;
  221. *(pszLDAPQuery + *piOutputIndex) = wchEQUAL;
  222. (*piOutputIndex) ++;
  223. }else return FALSE;
  224. }
  225. // Look for the special characters ( ) * and \ and escape them with a \
  226. LPWSTR pszEscapedValue = EscapeStringValue(strDN);
  227. if(*piOutputIndex + (int)wcslen(pszEscapedValue) < nLength){
  228. wcscpy(pszLDAPQuery + *piOutputIndex, pszEscapedValue);
  229. (*piOutputIndex) += wcslen(pszEscapedValue);
  230. }else return FALSE;
  231. delete [] pszEscapedValue;
  232. SysFreeString(strDN);
  233. bRetVal = TRUE;
  234. }
  235. }
  236. pADsPathName->Release();
  237. }
  238. SysFreeString(strADSIPath);
  239. return bRetVal;
  240. }
  241. // Write a '('
  242. if(*piOutputIndex + 1 < nLength){
  243. pszLDAPQuery[(*piOutputIndex) ++] = wchLEFT_BRACKET;
  244. }
  245. switch(iOperator)
  246. {
  247. case SQL_LEVEL_1_TOKEN::OP_EQUAL:
  248. {
  249. // Special case where we use '*' LDAP operator
  250. // is NULL translates to !( x=*)
  251. if(pValue->vt == VT_NULL)
  252. {
  253. if(*piOutputIndex + 2 < nLength){
  254. // The '!'
  255. *(pszLDAPQuery + *piOutputIndex) = wchNOT;
  256. (*piOutputIndex) ++;
  257. // The '('
  258. *(pszLDAPQuery + *piOutputIndex) = wchLEFT_BRACKET;
  259. (*piOutputIndex) ++;
  260. }else return FALSE;
  261. if(!TranslateExpression(pszLDAPQuery, piOutputIndex, SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL, pszPropertyName, NULL, nLength))
  262. return FALSE;
  263. if(*piOutputIndex + 1 < nLength){
  264. // The ')'
  265. *(pszLDAPQuery + *piOutputIndex) = wchRIGHT_BRACKET;
  266. (*piOutputIndex) ++;
  267. }else return FALSE;
  268. break;
  269. }
  270. else
  271. {
  272. // Followthru
  273. }
  274. }
  275. case SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN:
  276. case SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN:
  277. {
  278. // Get the LDAP name of the property
  279. LPWSTR pszLDAPName = CLDAPHelper::UnmangleWBEMNameToLDAP(pszPropertyName);
  280. if(*piOutputIndex + (int)wcslen(pszLDAPName) < nLength){
  281. wcscpy(pszLDAPQuery + *piOutputIndex, pszLDAPName);
  282. *piOutputIndex += wcslen(pszLDAPName);
  283. }else return FALSE;
  284. delete [] pszLDAPName;
  285. // Put the LDAP Operator
  286. if(iOperator == SQL_LEVEL_1_TOKEN::OP_EQUAL)
  287. {
  288. if(*piOutputIndex + 1 < nLength){
  289. *(pszLDAPQuery + *piOutputIndex) = wchEQUAL;
  290. (*piOutputIndex) ++;
  291. }else return FALSE;
  292. }
  293. else if(iOperator == SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN)
  294. {
  295. if(*piOutputIndex + 2 < nLength){
  296. wcscpy(pszLDAPQuery + *piOutputIndex, pszGE);
  297. *piOutputIndex += 2;
  298. }else return FALSE;
  299. }
  300. else
  301. {
  302. if(*piOutputIndex + 2 < nLength){
  303. wcscpy(pszLDAPQuery + *piOutputIndex, pszLE);
  304. *piOutputIndex += 2;
  305. }else return FALSE;
  306. }
  307. // Put the value of the property
  308. if(!TranslateValueToLDAP(pszLDAPQuery, piOutputIndex, pValue))
  309. return FALSE;
  310. }
  311. break;
  312. case SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
  313. {
  314. // Special case for use of '*'
  315. if(pValue == NULL || pValue->vt == VT_NULL)
  316. {
  317. // Get the LDAP name of the property
  318. LPWSTR pszLDAPName = CLDAPHelper::UnmangleWBEMNameToLDAP(pszPropertyName);
  319. if(*piOutputIndex + (int)wcslen(pszLDAPName) < nLength){
  320. wcscpy(pszLDAPQuery + *piOutputIndex, pszLDAPName);
  321. *piOutputIndex += wcslen(pszLDAPName);
  322. }else return FALSE;
  323. delete [] pszLDAPName;
  324. if(*piOutputIndex + 2 < nLength){
  325. *(pszLDAPQuery + *piOutputIndex) = wchEQUAL;
  326. (*piOutputIndex) ++;
  327. *(pszLDAPQuery + *piOutputIndex) = wchSTAR;
  328. (*piOutputIndex) ++;
  329. }else return FALSE;
  330. }
  331. else
  332. {
  333. if(*piOutputIndex + 2 < nLength){
  334. // The '!'
  335. *(pszLDAPQuery + *piOutputIndex) = wchNOT;
  336. (*piOutputIndex) ++;
  337. // The '('
  338. *(pszLDAPQuery + *piOutputIndex) = wchLEFT_BRACKET;
  339. (*piOutputIndex) ++;
  340. }else return FALSE;
  341. if(TranslateExpression(pszLDAPQuery, piOutputIndex, SQL_LEVEL_1_TOKEN::OP_EQUAL, pszPropertyName, pValue, nLength))
  342. {
  343. if(*piOutputIndex + 1 < nLength){
  344. // The ')'
  345. *(pszLDAPQuery + *piOutputIndex) = wchRIGHT_BRACKET;
  346. (*piOutputIndex) ++;
  347. }else return FALSE;
  348. }
  349. else
  350. return FALSE;
  351. }
  352. }
  353. break;
  354. case SQL_LEVEL_1_TOKEN::OP_LESSTHAN:
  355. {
  356. if(*piOutputIndex + 2 < nLength){
  357. // The '!'
  358. *(pszLDAPQuery + *piOutputIndex) = wchNOT;
  359. (*piOutputIndex) ++;
  360. // The '('
  361. *(pszLDAPQuery + *piOutputIndex) = wchLEFT_BRACKET;
  362. (*piOutputIndex) ++;
  363. }else return FALSE;
  364. if(TranslateExpression(pszLDAPQuery, piOutputIndex, SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN, pszPropertyName, pValue,nLength))
  365. {
  366. if(*piOutputIndex + 1 < nLength){
  367. // The ')'
  368. *(pszLDAPQuery + *piOutputIndex) = wchRIGHT_BRACKET;
  369. (*piOutputIndex) ++;
  370. }else return FALSE;
  371. }
  372. else
  373. return FALSE;
  374. }
  375. break;
  376. case SQL_LEVEL_1_TOKEN::OP_GREATERTHAN:
  377. {
  378. if(*piOutputIndex + 2 < nLength){
  379. // The '!'
  380. *(pszLDAPQuery + *piOutputIndex) = wchNOT;
  381. (*piOutputIndex) ++;
  382. // The '('
  383. *(pszLDAPQuery + *piOutputIndex) = wchLEFT_BRACKET;
  384. (*piOutputIndex) ++;
  385. }else return FALSE;
  386. if(TranslateExpression(pszLDAPQuery, piOutputIndex, SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN, pszPropertyName, pValue, nLength))
  387. {
  388. if(*piOutputIndex + 1 < nLength){
  389. // The ')'
  390. *(pszLDAPQuery + *piOutputIndex) = wchRIGHT_BRACKET;
  391. (*piOutputIndex) ++;
  392. }else return FALSE;
  393. }
  394. else
  395. return FALSE;
  396. }
  397. break;
  398. default:
  399. return FALSE;
  400. }
  401. if(*piOutputIndex + 1 < nLength){
  402. // Write a ')'
  403. pszLDAPQuery[(*piOutputIndex) ++] = wchRIGHT_BRACKET;
  404. } else return FALSE;
  405. return TRUE;
  406. }
  407. BOOLEAN QueryConvertor::TranslateValueToLDAP(LPWSTR pszLDAPQuery, int *piOutputIndex, VARIANT *pValue)
  408. {
  409. switch(pValue->vt)
  410. {
  411. case VT_BSTR:
  412. {
  413. // Look for the special characters ( ) * and \ and escape them with a \
  414. LPWSTR pszEscapedValue = EscapeStringValue(pValue->bstrVal);
  415. wcscpy(pszLDAPQuery + *piOutputIndex, pszEscapedValue);
  416. (*piOutputIndex) += wcslen(pszEscapedValue);
  417. delete [] pszEscapedValue;
  418. }
  419. break;
  420. case VT_I4:
  421. {
  422. WCHAR temp[18];
  423. swprintf(temp, L"%d", pValue->lVal);
  424. wcscpy(pszLDAPQuery + *piOutputIndex, temp);
  425. (*piOutputIndex) += wcslen(temp);
  426. }
  427. break;
  428. case VT_BOOL:
  429. {
  430. if(pValue->boolVal == VARIANT_TRUE)
  431. {
  432. wcscpy(pszLDAPQuery + *piOutputIndex, L"TRUE");
  433. (*piOutputIndex) += wcslen(L"TRUE");
  434. }
  435. else
  436. {
  437. wcscpy(pszLDAPQuery + *piOutputIndex, L"FALSE");
  438. (*piOutputIndex) += wcslen(L"FALSE");
  439. }
  440. }
  441. break;
  442. default:
  443. return FALSE;
  444. }
  445. return TRUE;
  446. }
  447. LPWSTR QueryConvertor::EscapeStringValue(LPCWSTR pszValue)
  448. {
  449. // Escape the special characters in a string value in a query
  450. LPWSTR pszRetValue = new WCHAR [wcslen(pszValue)*2 + 1];
  451. DWORD j=0;
  452. for(DWORD i=0; i<wcslen(pszValue); i++)
  453. {
  454. switch(pszValue[i])
  455. {
  456. case wchLEFT_BRACKET:
  457. pszRetValue[j++] = wchBACK_SLASH;
  458. pszRetValue[j++] = '2';
  459. pszRetValue[j++] = '8';
  460. break;
  461. case wchRIGHT_BRACKET:
  462. pszRetValue[j++] = wchBACK_SLASH;
  463. pszRetValue[j++] = '2';
  464. pszRetValue[j++] = '9';
  465. break;
  466. case wchSTAR:
  467. pszRetValue[j++] = wchBACK_SLASH;
  468. pszRetValue[j++] = '2';
  469. pszRetValue[j++] = 'a';
  470. break;
  471. case wchBACK_SLASH:
  472. pszRetValue[j++] = wchBACK_SLASH;
  473. pszRetValue[j++] = '5';
  474. pszRetValue[j++] = 'c';
  475. break;
  476. default:
  477. pszRetValue[j++] = pszValue[i];
  478. break;
  479. }
  480. }
  481. pszRetValue[j] = NULL;
  482. return pszRetValue;
  483. }