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.

409 lines
12 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  4. //
  5. // FRQueryEx.cpp
  6. //
  7. // Purpose: Extended query support functions
  8. //
  9. //***************************************************************************
  10. #include "precomp.h"
  11. #include <smartptr.h>
  12. #include <analyser.h>
  13. #include <FRQueryEx.h>
  14. #include <assertbreak.h>
  15. #include <utils.h>
  16. #include "multiplat.h"
  17. CFrameworkQueryEx::CFrameworkQueryEx()
  18. {
  19. }
  20. CFrameworkQueryEx::~CFrameworkQueryEx()
  21. {
  22. }
  23. // See comments in header
  24. BOOL CFrameworkQueryEx::Is3TokenOR(LPCWSTR wszProp1, LPCWSTR wszProp2, VARIANT &vVar1, VARIANT &vVar2)
  25. {
  26. BOOL bRet = FALSE;
  27. if ((m_pLevel1RPNExpression != NULL) &&
  28. (m_pLevel1RPNExpression->nNumTokens == 3) &&
  29. (m_pLevel1RPNExpression->pArrayOfTokens[2].nTokenType == SQL_LEVEL_1_TOKEN::TOKEN_OR) &&
  30. (m_pLevel1RPNExpression->pArrayOfTokens[0].nTokenType == SQL_LEVEL_1_TOKEN::OP_EXPRESSION) &&
  31. (m_pLevel1RPNExpression->pArrayOfTokens[1].nTokenType == SQL_LEVEL_1_TOKEN::OP_EXPRESSION) &&
  32. (m_pLevel1RPNExpression->pArrayOfTokens[0].nOperator == SQL_LEVEL_1_TOKEN::OP_EQUAL) &&
  33. (m_pLevel1RPNExpression->pArrayOfTokens[1].nOperator == SQL_LEVEL_1_TOKEN::OP_EQUAL)
  34. )
  35. {
  36. if (
  37. (_wcsicmp(m_pLevel1RPNExpression->pArrayOfTokens[0].pPropertyName, wszProp1) == 0) &&
  38. (_wcsicmp(m_pLevel1RPNExpression->pArrayOfTokens[1].pPropertyName, wszProp2) == 0))
  39. {
  40. VariantClear(&vVar1);
  41. VariantClear(&vVar2);
  42. if (FAILED(VariantCopy(&vVar1, &m_pLevel1RPNExpression->pArrayOfTokens[0].vConstValue)) ||
  43. FAILED(VariantCopy(&vVar2, &m_pLevel1RPNExpression->pArrayOfTokens[1].vConstValue)) )
  44. {
  45. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  46. }
  47. bRet = TRUE;
  48. }
  49. else if (
  50. (_wcsicmp(m_pLevel1RPNExpression->pArrayOfTokens[0].pPropertyName, wszProp2) == 0) &&
  51. (_wcsicmp(m_pLevel1RPNExpression->pArrayOfTokens[1].pPropertyName, wszProp1) == 0))
  52. {
  53. VariantClear(&vVar1);
  54. VariantClear(&vVar2);
  55. if (FAILED(VariantCopy(&vVar1, &m_pLevel1RPNExpression->pArrayOfTokens[1].vConstValue)) ||
  56. FAILED(VariantCopy(&vVar2, &m_pLevel1RPNExpression->pArrayOfTokens[0].vConstValue)) )
  57. {
  58. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  59. }
  60. bRet = TRUE;
  61. }
  62. }
  63. return bRet;
  64. }
  65. // See comments in header
  66. BOOL CFrameworkQueryEx::IsNTokenAnd(CHStringArray &sarr, CHPtrArray &sPtrArr)
  67. {
  68. BOOL bRet = FALSE;
  69. if (m_pLevel1RPNExpression != NULL)
  70. {
  71. // Walk all the tokens
  72. for (DWORD x = 0; x < m_pLevel1RPNExpression->nNumTokens; x++)
  73. {
  74. // If this is an expression token, and the expression is of type '='
  75. if ((m_pLevel1RPNExpression->pArrayOfTokens[x].nTokenType == SQL_LEVEL_1_TOKEN::OP_EXPRESSION) &&
  76. (m_pLevel1RPNExpression->pArrayOfTokens[x].nOperator == SQL_LEVEL_1_TOKEN::OP_EQUAL))
  77. {
  78. // convert the property name to upper case. This facilitates checking
  79. // to see if it is already in the list.
  80. _wcsupr(m_pLevel1RPNExpression->pArrayOfTokens[x].pPropertyName);
  81. // Check to see if we have already seen this property.
  82. if (IsInList(sarr, m_pLevel1RPNExpression->pArrayOfTokens[x].pPropertyName) == -1)
  83. {
  84. // Add the name to the list
  85. sarr.Add(m_pLevel1RPNExpression->pArrayOfTokens[x].pPropertyName);
  86. // Create a new variant for the value and add it to the list
  87. LPVOID pValue = new variant_t(m_pLevel1RPNExpression->pArrayOfTokens[x].vConstValue);
  88. try
  89. {
  90. sPtrArr.Add(pValue);
  91. }
  92. catch ( ... )
  93. {
  94. delete pValue;
  95. sarr.RemoveAll();
  96. DWORD dwSize = sPtrArr.GetSize();
  97. for (x = 0; x < dwSize; x++)
  98. {
  99. delete sPtrArr[x];
  100. }
  101. sPtrArr.RemoveAll();
  102. throw ;
  103. }
  104. bRet = TRUE;
  105. }
  106. else
  107. {
  108. // Already in list
  109. bRet = FALSE;
  110. break;
  111. }
  112. }
  113. // It wasn't an expression token, if it's not AND, we've failed.
  114. else if (m_pLevel1RPNExpression->pArrayOfTokens[x].nTokenType != SQL_LEVEL_1_TOKEN::TOKEN_AND)
  115. {
  116. bRet = FALSE;
  117. break;
  118. }
  119. }
  120. // If this didn't work, let's clean the CHPtrArray and CHStringArray
  121. if (!bRet)
  122. {
  123. sarr.RemoveAll();
  124. DWORD dwSize = sPtrArr.GetSize();
  125. for (x = 0; x < dwSize; x++)
  126. {
  127. delete sPtrArr[x];
  128. }
  129. sPtrArr.RemoveAll();
  130. }
  131. }
  132. return bRet;
  133. }
  134. // see comments in header
  135. HRESULT CFrameworkQueryEx::GetValuesForProp(LPCWSTR wszPropName, std::vector<int>& vectorValues)
  136. {
  137. HRESULT hr = WBEM_S_NO_ERROR;
  138. if (m_pLevel1RPNExpression != NULL)
  139. {
  140. hr = CQueryAnalyser::GetValuesForProp(m_pLevel1RPNExpression, wszPropName, vectorValues);
  141. if (SUCCEEDED(hr))
  142. {
  143. // Remove duplicates
  144. for (int x = 1; x < vectorValues.size(); x++)
  145. {
  146. for (int y = 0; y < x; y++)
  147. {
  148. if (vectorValues[y] == vectorValues[x])
  149. {
  150. vectorValues.erase(vectorValues.begin() + x);
  151. x--;
  152. }
  153. }
  154. }
  155. }
  156. else
  157. {
  158. vectorValues.clear();
  159. if (hr == WBEMESS_E_REGISTRATION_TOO_BROAD)
  160. {
  161. hr = WBEM_S_NO_ERROR;
  162. }
  163. }
  164. }
  165. else
  166. {
  167. ASSERT_BREAK(FALSE);
  168. vectorValues.clear();
  169. hr = WBEM_E_FAILED;
  170. }
  171. return hr;
  172. }
  173. // see comments in header
  174. HRESULT CFrameworkQueryEx::GetValuesForProp(LPCWSTR wszPropName, std::vector<_variant_t>& vectorValues)
  175. {
  176. HRESULT hr = WBEM_S_NO_ERROR;
  177. if (wszPropName && (m_pLevel1RPNExpression != NULL))
  178. {
  179. hr = CQueryAnalyser::GetValuesForProp(m_pLevel1RPNExpression, wszPropName, vectorValues);
  180. if (SUCCEEDED(hr))
  181. {
  182. // If this is a reference property, we need to normalize the names to a common form
  183. // so the removal of duplicates works correctly.
  184. if (IsReference(wszPropName))
  185. {
  186. // Get the current computer name
  187. CHString sOutPath, sComputerName;
  188. DWORD dwBufferLength = MAX_COMPUTERNAME_LENGTH + 1;
  189. FRGetComputerName(sComputerName.GetBuffer( dwBufferLength ), &dwBufferLength);
  190. sComputerName.ReleaseBuffer();
  191. if (sComputerName.IsEmpty())
  192. {
  193. sComputerName = L"DEFAULT";
  194. }
  195. DWORD dwRet = e_OK;
  196. // Normalize the path names. Try leaving the property names alone
  197. for (int x = 0; x < vectorValues.size(); x++)
  198. {
  199. // If we failed to parse the path, or if the namespace isn't our namespace, delete
  200. // the entry.
  201. if ( (V_VT(&vectorValues[x]) == VT_BSTR) &&
  202. (dwRet = NormalizePath(V_BSTR(&vectorValues[x]), sComputerName, GetNamespace(), 0, sOutPath)) == e_OK)
  203. {
  204. vectorValues[x] = sOutPath;
  205. }
  206. else if (dwRet == e_NullName)
  207. {
  208. break;
  209. }
  210. else
  211. {
  212. vectorValues.erase(vectorValues.begin() + x);
  213. x--;
  214. }
  215. }
  216. // If the key property names of any of the values were null, we have to set them all
  217. // to null.
  218. if (dwRet == e_NullName)
  219. {
  220. for (int x = 0; x < vectorValues.size(); x++)
  221. {
  222. // If we failed to parse the path, or if the namespace isn't our namespace, delete
  223. // the entry.
  224. if ( (V_VT(&vectorValues[x]) == VT_BSTR) &&
  225. (dwRet = NormalizePath(V_BSTR(&vectorValues[x]), sComputerName, GetNamespace(), NORMALIZE_NULL, sOutPath)) == e_OK)
  226. {
  227. vectorValues[x] = sOutPath;
  228. }
  229. else
  230. {
  231. vectorValues.erase(vectorValues.begin() + x);
  232. x--;
  233. }
  234. }
  235. }
  236. }
  237. // Remove duplicates
  238. for (int x = 1; x < vectorValues.size(); x++)
  239. {
  240. for (int y = 0; y < x; y++)
  241. {
  242. if (vectorValues[y] == vectorValues[x])
  243. {
  244. vectorValues.erase(vectorValues.begin() + x);
  245. x--;
  246. }
  247. }
  248. }
  249. }
  250. else
  251. {
  252. vectorValues.clear();
  253. if (hr == WBEMESS_E_REGISTRATION_TOO_BROAD)
  254. {
  255. hr = WBEM_S_NO_ERROR;
  256. }
  257. }
  258. }
  259. else
  260. {
  261. ASSERT_BREAK(FALSE);
  262. vectorValues.clear();
  263. hr = WBEM_E_FAILED;
  264. }
  265. return hr;
  266. }
  267. // See comments in header
  268. void CFrameworkQueryEx::GetPropertyBitMask(const CHPtrArray &Properties, LPVOID pBits)
  269. {
  270. if (AllPropertiesAreRequired())
  271. {
  272. SetAllBits(pBits, Properties.GetSize());
  273. }
  274. else
  275. {
  276. ZeroAllBits(pBits, Properties.GetSize());
  277. CHString sProperty;
  278. for (DWORD x=0; x < Properties.GetSize(); x++)
  279. {
  280. sProperty = (WCHAR *)Properties[x];
  281. sProperty.MakeUpper();
  282. if (IsInList(m_csaPropertiesRequired, sProperty) != -1)
  283. {
  284. SetBit(pBits, x);
  285. }
  286. }
  287. }
  288. }
  289. HRESULT CFrameworkQueryEx::InitEx(
  290. const BSTR bstrQueryFormat,
  291. const BSTR bstrQuery,
  292. long lFlags,
  293. CHString &sNamespace
  294. )
  295. {
  296. HRESULT hr = WBEM_S_NO_ERROR;
  297. // parse the query using the parsing interface
  298. IWbemQueryPtr pQueryInterface(CLSID_WbemQuery);
  299. hr = pQueryInterface->Parse(bstrQueryFormat, bstrQuery, 0);
  300. if (SUCCEEDED(hr))
  301. {
  302. ULONG uFeatureCount = WMIQ_LF_LAST;
  303. ULONG uFeatures[WMIQ_LF_LAST];
  304. hr = pQueryInterface->TestLanguageFeatures(0, &uFeatureCount, uFeatures);
  305. if (SUCCEEDED(hr))
  306. {
  307. if (uFeatures[0] == WMIQ_LF1_BASIC_SELECT)
  308. {
  309. // if this is a nova compatible select statement
  310. hr = Init(bstrQueryFormat, bstrQuery, lFlags, sNamespace);
  311. }
  312. else if (uFeatures[0] == WMIQ_LF18_ASSOCIATONS) // add others?
  313. {
  314. // Save the detailed query
  315. m_sQueryEx = bstrQuery;
  316. // create select statement from class name
  317. SWbemAssocQueryInf aqfBuff;
  318. hr = pQueryInterface->GetQueryInfo(WMIQ_ANALYSIS_ASSOC_QUERY, WMIQ_ASSOCQ_ASSOCIATORS, sizeof(aqfBuff), &aqfBuff);
  319. if (SUCCEEDED(hr))
  320. {
  321. CHString sQuery;
  322. // I don't know how to tell if this is an associators or a reference
  323. if (true)
  324. {
  325. sQuery.Format(L"Select * from %s", aqfBuff.m_pszAssocClass);
  326. }
  327. // Store the more basic query
  328. hr = Init(bstrQueryFormat, bstrQuery, lFlags, sNamespace);
  329. }
  330. }
  331. else
  332. {
  333. hr = WBEM_E_INVALID_QUERY;
  334. }
  335. }
  336. }
  337. return hr;
  338. }
  339. bool CFrameworkQueryEx::IsExtended()
  340. {
  341. return !m_sQueryEx.IsEmpty();
  342. }