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.

655 lines
18 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. instancehelper.cpp
  5. Abstract:
  6. Implementation of:
  7. CInstanceHelper
  8. Author:
  9. Mohit Srivastava 22-Mar-2001
  10. Revision History:
  11. --*/
  12. //
  13. // for metabase.h
  14. //
  15. extern "C" {
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. }
  20. #include <comdef.h>
  21. #include "iisfiles.h"
  22. #include "instancehelper.h"
  23. #include "utils.h"
  24. #include "iiswmimsg.h"
  25. #include "globalconstants.h"
  26. #include "adminacl.h"
  27. #include "ipsecurity.h"
  28. #include "metabase.h"
  29. #include "SmartPointer.h"
  30. #include "schemadynamic.h"
  31. extern CDynSchema* g_pDynSch;
  32. CInstanceHelper::CInstanceHelper(
  33. ParsedObjectPath* i_pParsedObjPath,
  34. CWbemServices* i_pNamespace) :
  35. m_PathParser(e_ParserAcceptRelativeNamespace)
  36. /*++
  37. Synopsis:
  38. Use this constructor when you have already parsed the object path.
  39. Caller owns the ParsedObjectPath.
  40. Arguments: [i_pParsedObjPath] -
  41. [i_pNamespace] -
  42. --*/
  43. {
  44. Init(i_pParsedObjPath, i_pNamespace);
  45. }
  46. CInstanceHelper::CInstanceHelper(
  47. BSTR i_bstrObjPath,
  48. CWbemServices* i_pNamespace) :
  49. m_PathParser(e_ParserAcceptRelativeNamespace)
  50. /*++
  51. Synopsis:
  52. Use this constructor when have not already parsed the object path.
  53. Arguments: [i_bstrObjPath] -
  54. [i_pNamespace] -
  55. --*/
  56. {
  57. DBG_ASSERT(i_bstrObjPath != NULL);
  58. DBG_ASSERT(i_pNamespace != NULL);
  59. TSmartPointer<ParsedObjectPath> spParsedObject;
  60. HRESULT hr = WBEM_S_NO_ERROR;
  61. hr = CUtils::ParserErrToHR( m_PathParser.Parse(i_bstrObjPath, &spParsedObject) );
  62. THROW_ON_ERROR(hr);
  63. Init(spParsedObject, i_pNamespace);
  64. m_pParsedObjPath = spParsedObject;
  65. spParsedObject = NULL;
  66. m_bOwnObjPath = true;
  67. }
  68. void CInstanceHelper::Init(
  69. ParsedObjectPath* i_pParsedObjPath,
  70. CWbemServices* i_pNamespace)
  71. /*++
  72. Synopsis:
  73. Called by constructors.
  74. Arguments: [i_pParsedObjPath] -
  75. [i_pNamespace] -
  76. --*/
  77. {
  78. m_pWmiClass = NULL;
  79. m_pWmiAssoc = NULL;
  80. DBG_ASSERT(i_pParsedObjPath != NULL);
  81. DBG_ASSERT(i_pNamespace != NULL);
  82. HRESULT hr = WBEM_S_NO_ERROR;
  83. if(CUtils::GetClass(i_pParsedObjPath->m_pClass,&m_pWmiClass))
  84. {
  85. }
  86. else if(CUtils::GetAssociation(i_pParsedObjPath->m_pClass,&m_pWmiAssoc))
  87. {
  88. }
  89. else
  90. {
  91. THROW_ON_ERROR(WBEM_E_INVALID_CLASS);
  92. }
  93. m_pParsedObjPath = i_pParsedObjPath;
  94. m_bOwnObjPath = false;
  95. m_pNamespace = i_pNamespace;
  96. THROW_ON_ERROR(hr);
  97. }
  98. void CInstanceHelper::GetAssociation(
  99. IWbemClassObject** o_ppObj,
  100. bool i_bVerifyLeft, //default(true)
  101. bool i_bVerifyRight) //default(true)
  102. /*++
  103. Synopsis:
  104. Specifying i_bVerifyLeft or i_bVerifyRight can be expensive, especially
  105. during enumeration. If you have already verified prior to calling this
  106. function that the left and/or right parts exist, then set these params
  107. to false.
  108. Arguments: [o_ppObj] - The WMI association that you "indicate" to WMI.
  109. [i_bVerifyLeft] - Verify left part of the association is valid.
  110. [i_bVerifyRight] - Verify right part of association is valid.
  111. --*/
  112. {
  113. DBG_ASSERT(o_ppObj != NULL);
  114. CComPtr<IWbemClassObject> spObj; // This is the obj that the client gets back
  115. HRESULT hr = WBEM_S_NO_ERROR;
  116. if(m_pParsedObjPath->m_dwNumKeys < 2)
  117. {
  118. THROW_ON_ERROR(WBEM_E_INVALID_CLASS);
  119. }
  120. KeyRef* pkrLeft = NULL;
  121. KeyRef* pkrRight = NULL;
  122. for(ULONG i = 0; i < m_pParsedObjPath->m_dwNumKeys; i++)
  123. {
  124. KeyRef* pkr = m_pParsedObjPath->m_paKeys[i];
  125. if(pkr->m_pName)
  126. {
  127. if( !pkrLeft &&
  128. _wcsicmp(pkr->m_pName, m_pWmiAssoc->pType->pszLeft) == 0 )
  129. {
  130. pkrLeft = pkr;
  131. }
  132. if( !pkrRight &&
  133. _wcsicmp(pkr->m_pName, m_pWmiAssoc->pType->pszRight) == 0 )
  134. {
  135. pkrRight = pkr;
  136. }
  137. }
  138. }
  139. if( !pkrLeft || !pkrRight ||
  140. pkrLeft->m_vValue.vt != VT_BSTR ||
  141. pkrRight->m_vValue.vt != VT_BSTR ||
  142. pkrLeft->m_vValue.bstrVal == NULL ||
  143. pkrRight->m_vValue.bstrVal == NULL )
  144. {
  145. THROW_ON_ERROR(WBEM_E_INVALID_OBJECT_PATH);
  146. }
  147. //
  148. // Now verify the two object paths are valid
  149. //
  150. bool abVerify[2];
  151. abVerify[0] = i_bVerifyLeft;
  152. abVerify[1] = i_bVerifyRight;
  153. KeyRef* apKr[2];
  154. apKr[0] = pkrLeft;
  155. apKr[1] = pkrRight;
  156. if(abVerify[0] || abVerify[1])
  157. {
  158. CMetabase metabase;
  159. CComPtr<IWbemClassObject> spObjTemp;
  160. for(ULONG i = 0; i < 2; i++)
  161. {
  162. if(abVerify[i])
  163. {
  164. spObjTemp = NULL;
  165. CInstanceHelper InstanceHelper(apKr[i]->m_vValue.bstrVal, m_pNamespace);
  166. if(InstanceHelper.IsAssoc())
  167. {
  168. THROW_ON_ERROR(WBEM_E_NOT_FOUND);
  169. }
  170. InstanceHelper.GetInstance(
  171. false,
  172. &metabase,
  173. &spObjTemp);
  174. }
  175. }
  176. }
  177. hr = CUtils::CreateEmptyInstance(m_pParsedObjPath->m_pClass, m_pNamespace, &spObj);
  178. THROW_ON_ERROR(hr);
  179. hr = spObj->Put(pkrLeft->m_pName, 0, &pkrLeft->m_vValue, 0);
  180. THROW_ON_ERROR(hr);
  181. hr = spObj->Put(pkrRight->m_pName, 0, &pkrRight->m_vValue, 0);
  182. THROW_ON_ERROR(hr);
  183. //
  184. // Set out parameters on success
  185. //
  186. *o_ppObj = spObj;
  187. (*o_ppObj)->AddRef();
  188. }
  189. void CInstanceHelper::GetInstance(
  190. bool i_bCreateKeyIfNotExist,
  191. CMetabase* io_pMetabase,
  192. IWbemClassObject** o_ppObj,
  193. SQL_LEVEL_1_RPN_EXPRESSION_EXT* i_pExp) // default(NULL)
  194. /*++
  195. Synopsis:
  196. Will throw an exception on failure (generallly instance not found in mb).
  197. If GetInstance finds the instance in the metabase, but i_pExp was specified,
  198. it is possible *o_ppObj will not be populated with an instance.
  199. This is a SUCCESS case.
  200. Arguments: [i_bCreateKeyIfNotExist] -
  201. [io_pMetabase] -
  202. [o_ppObj] - The only success case where *o_ppObj will be NULL
  203. is if it the instance is found in the metabase but i_pExp
  204. (i.e. a query) is specified and the query doesn't match.
  205. [i_pExp] - An optional query.
  206. --*/
  207. {
  208. DBG_ASSERT(o_ppObj != NULL);
  209. DBG_ASSERT(io_pMetabase != NULL);
  210. *o_ppObj = NULL;
  211. CComPtr<IWbemClassObject> spObj;
  212. HRESULT hr = WBEM_S_NO_ERROR;
  213. METABASE_PROPERTY** ppmbp;
  214. _bstr_t bstrMbPath;
  215. METADATA_HANDLE hKey = NULL;
  216. VARIANT vtTrue;
  217. vtTrue.boolVal = VARIANT_TRUE;
  218. vtTrue.vt = VT_BOOL;
  219. hr = CUtils::CreateEmptyInstance(m_pParsedObjPath->m_pClass, m_pNamespace, &spObj);
  220. THROW_ON_ERROR(hr);
  221. CUtils::GetMetabasePath(spObj, m_pParsedObjPath, m_pWmiClass, bstrMbPath);
  222. //
  223. // if AdminACL
  224. //
  225. if( m_pWmiClass->pkt == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACL ||
  226. m_pWmiClass->pkt == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACE
  227. )
  228. {
  229. CAdminACL objACL;
  230. hr = objACL.OpenSD(bstrMbPath, *io_pMetabase);
  231. if(SUCCEEDED(hr))
  232. hr = objACL.GetObjectAsync(spObj, m_pParsedObjPath, m_pWmiClass);
  233. THROW_ON_ERROR(hr);
  234. *o_ppObj = spObj;
  235. (*o_ppObj)->AddRef();
  236. return;
  237. }
  238. //
  239. // if IPSecurity
  240. //
  241. else if( m_pWmiClass->pkt == &METABASE_KEYTYPE_DATA::s_TYPE_IPSecurity )
  242. {
  243. CIPSecurity IPSecurity;
  244. hr = IPSecurity.OpenSD(bstrMbPath, *io_pMetabase);
  245. if(SUCCEEDED(hr))
  246. hr = IPSecurity.GetObjectAsync(spObj);
  247. THROW_ON_ERROR(hr);
  248. *o_ppObj = spObj;
  249. (*o_ppObj)->AddRef();
  250. return;
  251. }
  252. if(!i_bCreateKeyIfNotExist)
  253. {
  254. hKey = io_pMetabase->OpenKey(bstrMbPath, false);
  255. }
  256. else
  257. {
  258. hKey = io_pMetabase->CreateKey(bstrMbPath);
  259. }
  260. _variant_t vt;
  261. //
  262. // If anything throws, CacheFree and then CloseKey is called automatically
  263. //
  264. io_pMetabase->CacheInit(hKey);
  265. //
  266. // Make sure requested keytype matches the keytype set at the node
  267. //
  268. if(!i_bCreateKeyIfNotExist)
  269. {
  270. io_pMetabase->Get(hKey, &METABASE_PROPERTY_DATA::s_KeyType, m_pNamespace, vt, NULL, NULL);
  271. if( vt.vt != VT_BSTR ||
  272. vt.bstrVal == NULL ||
  273. !CUtils::CompareKeyType(vt.bstrVal, m_pWmiClass->pkt) )
  274. {
  275. CIIsProvException e;
  276. e.SetMC(WBEM_E_NOT_FOUND, IISWMI_INVALID_KEYTYPE, NULL);
  277. throw e;
  278. }
  279. vt.Clear();
  280. }
  281. //
  282. // User wants to filter number of instances returned
  283. // Walk thru all filters, and try and get these first.
  284. //
  285. if(i_pExp && !i_pExp->GetContainsOrOrNot())
  286. {
  287. SQL_LEVEL_1_TOKEN* pToken = i_pExp->m_pSqlExpr->pArrayOfTokens;
  288. METABASE_PROPERTY* pMbpQuery = NULL;
  289. for(int i = 0; i < i_pExp->m_pSqlExpr->nNumTokens; i++, pToken++)
  290. {
  291. BOOL bInherited = false;
  292. BOOL bDefault = false;
  293. if( pToken->nTokenType == SQL_LEVEL_1_TOKEN::OP_EXPRESSION )
  294. {
  295. hr = g_pDynSch->GetHashProps()->Wmi_GetByKey(
  296. pToken->pPropertyName,
  297. &pMbpQuery);
  298. if(FAILED(hr))
  299. {
  300. if(_wcsicmp(pToken->pPropertyName, m_pWmiClass->pszKeyName) == 0)
  301. {
  302. //
  303. // User requested the name property which is not in the schema by
  304. // design.
  305. //
  306. hr = spObj->Get(m_pWmiClass->pszKeyName, 0, &vt, NULL, NULL);
  307. THROW_ON_ERROR(hr);
  308. }
  309. else
  310. {
  311. //
  312. // User requested a property that is not in the schema
  313. //
  314. DBGPRINTF( (DBG_CONTEXT,
  315. "Property %ws not in schema\n", pToken->pPropertyName) );
  316. THROW_ON_ERROR(WBEM_E_INVALID_QUERY);
  317. }
  318. }
  319. else
  320. {
  321. io_pMetabase->Get(hKey, pMbpQuery, m_pNamespace, vt, &bInherited, &bDefault);
  322. }
  323. if(!CheckForQueryMatch(pToken, &vt))
  324. {
  325. //
  326. // We don't need to return this instance.
  327. // value from metabase is not what user wanted.
  328. //
  329. io_pMetabase->CacheFree();
  330. io_pMetabase->CloseKey(hKey);
  331. return;
  332. }
  333. PutProperty(spObj, pToken->pPropertyName, &vt, bInherited, bDefault);
  334. vt.Clear();
  335. }
  336. }
  337. }
  338. //
  339. // Walk thru all the properties in the class and put them in an instance
  340. // we will return back to WMI
  341. //
  342. for (ppmbp=m_pWmiClass->ppmbp;*ppmbp; ppmbp++)
  343. {
  344. BOOL bInherited = false;
  345. BOOL bDefault = false;
  346. BOOL bSkipProp = false;
  347. if(i_pExp)
  348. {
  349. if(!i_pExp->FindRequestedProperty((*ppmbp)->pszPropName))
  350. {
  351. //
  352. // User did not request this property
  353. //
  354. bSkipProp = true;
  355. }
  356. else if(!i_pExp->GetContainsOrOrNot() && i_pExp->GetFilter((*ppmbp)->pszPropName))
  357. {
  358. //
  359. // Right above for loop, we handled all filters already.
  360. //
  361. bSkipProp = true;
  362. }
  363. }
  364. if( !bSkipProp )
  365. {
  366. io_pMetabase->Get(hKey, *ppmbp, m_pNamespace, vt, &bInherited, &bDefault);
  367. _bstr_t bstrPropName = (*ppmbp)->pszPropName;
  368. PutProperty(spObj, bstrPropName, &vt, bInherited, bDefault);
  369. vt.Clear();
  370. }
  371. }
  372. io_pMetabase->CacheFree();
  373. io_pMetabase->CloseKey(hKey);
  374. hKey = NULL;
  375. //
  376. // Set qualifiers
  377. //
  378. LPCWSTR awszNames[2] = { g_wszInstanceName, g_wszInstanceExists };
  379. VARIANT apvValues[2];
  380. apvValues[0].bstrVal = bstrMbPath;
  381. apvValues[0].vt = VT_BSTR;
  382. apvValues[1].boolVal = vtTrue.boolVal;
  383. apvValues[1].vt = vtTrue.vt;
  384. hr = CUtils::SetQualifiers(spObj, awszNames, apvValues, 2,
  385. WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE);
  386. THROW_ON_ERROR(hr);
  387. //
  388. // Set out parameters on success
  389. //
  390. *o_ppObj = spObj;
  391. (*o_ppObj)->AddRef();
  392. }
  393. void CInstanceHelper::PutProperty(
  394. IWbemClassObject* i_pInstance,
  395. const BSTR i_bstrPropName,
  396. VARIANT* i_vtPropValue,
  397. BOOL i_bIsInherited,
  398. BOOL i_bIsDefault)
  399. {
  400. DBG_ASSERT(i_pInstance);
  401. DBG_ASSERT(i_bstrPropName);
  402. DBG_ASSERT(i_vtPropValue);
  403. HRESULT hr = WBEM_S_NO_ERROR;
  404. VARIANT vtTrue;
  405. vtTrue.boolVal = VARIANT_TRUE;
  406. vtTrue.vt = VT_BOOL;
  407. //
  408. // TODO: Log error if Put fails.
  409. //
  410. hr = i_pInstance->Put(i_bstrPropName, 0, i_vtPropValue, 0);
  411. if(FAILED(hr))
  412. {
  413. DBGPRINTF((
  414. DBG_CONTEXT,
  415. "The property %ws in class %ws is not in repository\n",
  416. i_bstrPropName,
  417. m_pWmiClass->pszClassName));
  418. }
  419. if(i_bIsInherited && SUCCEEDED(hr))
  420. {
  421. hr = CUtils::SetPropertyQualifiers(
  422. i_pInstance, i_bstrPropName, &g_wszIsInherit, &vtTrue, 1);
  423. THROW_ON_ERROR(hr);
  424. }
  425. else if(i_bIsDefault && SUCCEEDED(hr))
  426. {
  427. hr = CUtils::SetPropertyQualifiers(
  428. i_pInstance, i_bstrPropName, &g_wszIsDefault, &vtTrue, 1);
  429. THROW_ON_ERROR(hr);
  430. }
  431. }
  432. bool CInstanceHelper::CheckForQueryMatch(
  433. const SQL_LEVEL_1_TOKEN* i_pToken,
  434. const VARIANT* i_pvtMatch)
  435. /*++
  436. Synopsis:
  437. It's okay to return true even if there is not a match, but we should
  438. never do the opposite.
  439. Arguments: [i_pToken] -
  440. [i_pvtMatch] -
  441. Return Value:
  442. --*/{
  443. DBG_ASSERT(i_pToken);
  444. DBG_ASSERT(i_pvtMatch);
  445. DBG_ASSERT(i_pToken->nTokenType == SQL_LEVEL_1_TOKEN::OP_EXPRESSION);
  446. bool bTypesMatch = false;
  447. //
  448. // Used only for VT_BOOL and VT_I4
  449. //
  450. ULONG ulToken = 0;
  451. ULONG ulMatch = 0;
  452. if( i_pvtMatch->vt == i_pToken->vConstValue.vt )
  453. {
  454. bTypesMatch = true;
  455. }
  456. if(bTypesMatch)
  457. {
  458. switch(i_pvtMatch->vt)
  459. {
  460. case VT_BOOL:
  461. ulMatch = i_pvtMatch->boolVal ? 1 : 0;
  462. ulToken = i_pToken->vConstValue.boolVal ? 1 : 0;
  463. //
  464. // deliberate fall thru
  465. //
  466. case VT_I4:
  467. if(i_pvtMatch->vt == VT_I4)
  468. {
  469. ulMatch = i_pvtMatch->lVal;
  470. ulToken = i_pToken->vConstValue.lVal;
  471. }
  472. switch(i_pToken->nOperator)
  473. {
  474. case SQL_LEVEL_1_TOKEN::OP_EQUAL:
  475. if(ulMatch != ulToken)
  476. {
  477. return false;
  478. }
  479. break;
  480. case SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
  481. if(ulMatch == ulToken)
  482. {
  483. return false;
  484. }
  485. break;
  486. case SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN:
  487. if(ulMatch < ulToken)
  488. {
  489. return false;
  490. }
  491. break;
  492. case SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN:
  493. if(ulMatch > ulToken)
  494. {
  495. return false;
  496. }
  497. break;
  498. case SQL_LEVEL_1_TOKEN::OP_LESSTHAN:
  499. if(ulMatch >= ulToken)
  500. {
  501. return false;
  502. }
  503. break;
  504. case SQL_LEVEL_1_TOKEN::OP_GREATERTHAN:
  505. if(ulMatch <= ulToken)
  506. {
  507. return false;
  508. }
  509. break;
  510. }
  511. break;
  512. case VT_BSTR:
  513. if(i_pToken->vConstValue.bstrVal && i_pvtMatch->bstrVal)
  514. {
  515. int iWcsCmp = _wcsicmp(i_pvtMatch->bstrVal, i_pToken->vConstValue.bstrVal);
  516. switch(i_pToken->nOperator)
  517. {
  518. case SQL_LEVEL_1_TOKEN::OP_EQUAL:
  519. if(iWcsCmp != 0)
  520. {
  521. return false;
  522. }
  523. break;
  524. case SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL:
  525. if(iWcsCmp == 0)
  526. {
  527. return false;
  528. }
  529. break;
  530. case SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN:
  531. if(iWcsCmp < 0)
  532. {
  533. return false;
  534. }
  535. break;
  536. case SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN:
  537. if(iWcsCmp > 0)
  538. {
  539. return false;
  540. }
  541. break;
  542. case SQL_LEVEL_1_TOKEN::OP_LESSTHAN:
  543. if(iWcsCmp >= 0)
  544. {
  545. return false;
  546. }
  547. break;
  548. case SQL_LEVEL_1_TOKEN::OP_GREATERTHAN:
  549. if(iWcsCmp <= 0)
  550. {
  551. return false;
  552. }
  553. break;
  554. }
  555. }
  556. break;
  557. default:
  558. break;
  559. }
  560. }
  561. return true;
  562. }