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.

624 lines
15 KiB

  1. //***************************************************************************
  2. //
  3. // VPTASKSH.CPP
  4. //
  5. // Module: WBEM VIEW PROVIDER
  6. //
  7. // Purpose: Contains the helper taskobject implementation
  8. //
  9. // Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #include <provexpt.h>
  14. #include <provcoll.h>
  15. #include <provtempl.h>
  16. #include <provmt.h>
  17. #include <typeinfo.h>
  18. #include <process.h>
  19. #include <objbase.h>
  20. #include <objidl.h>
  21. #include <stdio.h>
  22. #include <wbemidl.h>
  23. #include <provcont.h>
  24. #include <provevt.h>
  25. #include <provthrd.h>
  26. #include <provlog.h>
  27. #include <cominit.h>
  28. #include <dsgetdc.h>
  29. #include <lmcons.h>
  30. #include <lmapibuf.h>
  31. #include <instpath.h>
  32. #include <genlex.h>
  33. #include <sql_1.h>
  34. #include <objpath.h>
  35. #include <vpdefs.h>
  36. #include <vpcfac.h>
  37. #include <vpquals.h>
  38. #include <vpserv.h>
  39. #include <vptasks.h>
  40. extern HRESULT SetSecurityLevelAndCloaking(IUnknown* pInterface, const wchar_t* prncpl);
  41. extern BOOL bAreWeLocal(WCHAR* pServerMachine);
  42. HelperTaskObject::HelperTaskObject(CViewProvServ *a_Provider,
  43. const wchar_t *a_ObjectPath, ULONG a_Flag, IWbemObjectSink *a_NotificationHandler ,
  44. IWbemContext *pCtx, IWbemServices* a_Serv, const wchar_t* prncpl,
  45. CWbemServerWrap* a_ServWrap)
  46. : WbemTaskObject (a_Provider, a_NotificationHandler, a_Flag, pCtx, a_Serv, a_ServWrap),
  47. m_ObjectPath(NULL),
  48. m_ParsedObjectPath(NULL),
  49. m_principal(NULL)
  50. {
  51. if (prncpl)
  52. {
  53. m_principal = UnicodeStringDuplicate(prncpl);
  54. }
  55. m_ObjectPath = UnicodeStringDuplicate(a_ObjectPath);
  56. }
  57. HelperTaskObject::~HelperTaskObject ()
  58. {
  59. if (m_ObjectPath != NULL)
  60. {
  61. delete [] m_ObjectPath;
  62. }
  63. if (NULL != m_ParsedObjectPath)
  64. {
  65. delete m_ParsedObjectPath;
  66. }
  67. if (m_principal)
  68. {
  69. delete [] m_principal;
  70. }
  71. }
  72. BOOL HelperTaskObject::Validate(CMap<CStringW, LPCWSTR, int, int>* parentMap)
  73. {
  74. CObjectPathParser objectPathParser;
  75. BOOL t_Status = ! objectPathParser.Parse ( m_ObjectPath , &m_ParsedObjectPath ) ;
  76. if ( t_Status )
  77. {
  78. t_Status = SetClass(m_ParsedObjectPath->m_pClass) ;
  79. if ( t_Status )
  80. {
  81. t_Status = ParseAndProcessClassQualifiers(m_ErrorObject, NULL, parentMap);
  82. }
  83. }
  84. return t_Status;
  85. }
  86. //Get the view object given the namespace and object path of the source and the namespace
  87. BOOL HelperTaskObject::DoQuery(ParsedObjectPath* parsedObjectPath, IWbemClassObject** pInst, int indx)
  88. {
  89. if (pInst == NULL)
  90. {
  91. return FALSE;
  92. }
  93. else
  94. {
  95. *pInst = NULL;
  96. }
  97. BOOL retVal = TRUE;
  98. //Create the query string
  99. SQL_LEVEL_1_RPN_EXPRESSION tmpRPN;
  100. tmpRPN.bsClassName = SysAllocString(m_ClassName);
  101. //need enough tokens to handle association work-around serverpath or dotpath or relpath
  102. SQL_LEVEL_1_TOKEN* tokArray = new SQL_LEVEL_1_TOKEN[(parsedObjectPath->m_dwNumKeys) * 6];
  103. DWORD dwToks = 0;
  104. for (int i = 0; retVal && (i < parsedObjectPath->m_dwNumKeys); i++)
  105. {
  106. POSITION pos = m_PropertyMap.GetStartPosition();
  107. while (retVal && pos)
  108. {
  109. CStringW key;
  110. CPropertyQualifierItem* propItem;
  111. m_PropertyMap.GetNextAssoc(pos, key, propItem);
  112. if (!propItem->m_SrcPropertyNames[indx].IsEmpty())
  113. {
  114. if (propItem->m_SrcPropertyNames[indx].CompareNoCase(parsedObjectPath->m_paKeys[i]->m_pName) == 0)
  115. {
  116. tokArray[dwToks].nTokenType = SQL_LEVEL_1_TOKEN::OP_EXPRESSION;
  117. tokArray[dwToks].nOperator = SQL_LEVEL_1_TOKEN::OP_EQUAL;
  118. tokArray[dwToks].pPropertyName = propItem->GetViewPropertyName().AllocSysString();
  119. if (m_bAssoc && (propItem->GetCimType() == CIM_REFERENCE))
  120. {
  121. retVal = TransposeReference(propItem, parsedObjectPath->m_paKeys[i]->m_vValue,
  122. &(tokArray[dwToks].vConstValue), TRUE, &m_ServerWrap);
  123. if (retVal)
  124. {
  125. //add the extra tokens if neccessary
  126. //for the association work-around
  127. wchar_t *t_pChar = tokArray[dwToks].vConstValue.bstrVal;
  128. //must be \\server\namespace and not \\.\namespace or relpath
  129. if ( (*t_pChar == L'\\') && (*(t_pChar+1) == L'\\') && (*(t_pChar+2) != L'.') )
  130. {
  131. //add the dotted version
  132. tokArray[dwToks + 1] = tokArray[dwToks++];
  133. t_pChar = tokArray[dwToks].vConstValue.bstrVal + 2;
  134. while (*t_pChar != L'\\')
  135. {
  136. t_pChar++;
  137. }
  138. --t_pChar;
  139. *t_pChar = L'.';
  140. --t_pChar;
  141. *t_pChar = L'\\';
  142. --t_pChar;
  143. *t_pChar = L'\\';
  144. BSTR t_strtmp = SysAllocString(t_pChar);
  145. VariantClear(&(tokArray[dwToks].vConstValue));
  146. VariantInit(&(tokArray[dwToks].vConstValue));
  147. tokArray[dwToks].vConstValue.vt = VT_BSTR;
  148. tokArray[dwToks].vConstValue.bstrVal = t_strtmp;
  149. dwToks++;
  150. tokArray[dwToks].nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  151. //add the relpath version
  152. tokArray[dwToks + 1] = tokArray[dwToks - 1];
  153. dwToks++;
  154. t_pChar = tokArray[dwToks].vConstValue.bstrVal + 4;
  155. while (*t_pChar != L':')
  156. {
  157. t_pChar++;
  158. }
  159. //exclude the ':'
  160. t_pChar++;
  161. t_strtmp = SysAllocString(t_pChar);
  162. VariantClear(&(tokArray[dwToks].vConstValue));
  163. VariantInit(&(tokArray[dwToks].vConstValue));
  164. tokArray[dwToks].vConstValue.vt = VT_BSTR;
  165. tokArray[dwToks].vConstValue.bstrVal = t_strtmp;
  166. dwToks++;
  167. tokArray[dwToks].nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR;
  168. }
  169. }
  170. }
  171. else
  172. {
  173. VariantInit(&(tokArray[dwToks].vConstValue));
  174. if (FAILED(VariantCopy(&(tokArray[dwToks].vConstValue),
  175. &(parsedObjectPath->m_paKeys[i]->m_vValue))))
  176. {
  177. throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR);
  178. }
  179. }
  180. //after every key add an AND
  181. //except if this is the first key since there is no where clause
  182. dwToks++;
  183. if (i != 0)
  184. {
  185. tokArray[dwToks++].nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND;
  186. }
  187. }
  188. }
  189. }
  190. }
  191. BSTR queryStr = NULL;
  192. if ( retVal && ((dwToks > 0) || (parsedObjectPath->m_dwNumKeys == 0)) )
  193. {
  194. CStringW qStr = GetStringFromRPN(&tmpRPN, dwToks, tokArray);
  195. queryStr = qStr.AllocSysString();
  196. }
  197. retVal = FALSE;
  198. if (queryStr != NULL)
  199. {
  200. //ExecQuery and test the results
  201. IEnumWbemClassObject *pEnum = NULL;
  202. HRESULT t_hr = WBEM_E_FAILED;
  203. BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1);
  204. if (m_ServerWrap)
  205. {
  206. IWbemContext * t_pCtx = m_Ctx;
  207. if (m_principal != NULL)
  208. {
  209. t_pCtx = NULL; //don't use context for remote calls
  210. }
  211. IWbemServices *ptmpServ = m_ServerWrap->GetServerOrProxy();
  212. if (ptmpServ)
  213. {
  214. t_hr = ptmpServ->ExecQuery(queryLBStr, queryStr, 0, t_pCtx, &pEnum);
  215. }
  216. if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && m_ServerWrap->IsRemote())
  217. {
  218. if ( SUCCEEDED(UpdateConnection(&m_ServerWrap, &ptmpServ)) )
  219. {
  220. if (ptmpServ)
  221. {
  222. t_hr = ptmpServ->ExecQuery(queryLBStr, queryStr, 0, t_pCtx, &pEnum);
  223. }
  224. }
  225. }
  226. if (ptmpServ)
  227. {
  228. m_ServerWrap->ReturnServerOrProxy(ptmpServ);
  229. }
  230. }
  231. if (SUCCEEDED(t_hr))
  232. {
  233. //set cloaking if remote
  234. //============================
  235. if ((m_principal == NULL) || ((m_principal != NULL) &&
  236. (S_OK == SetSecurityLevelAndCloaking(pEnum, m_principal))) )
  237. {
  238. if ( (m_principal != NULL) ||
  239. ((m_principal == NULL) && SUCCEEDED(SetSecurityLevelAndCloaking(pEnum, COLE_DEFAULT_PRINCIPAL))) )
  240. {
  241. ULONG uCount = 0;
  242. IWbemClassObject* pObjs[2];
  243. pObjs[0] = NULL;
  244. pObjs[1] = NULL;
  245. //must be exactly one result...
  246. if ( SUCCEEDED(pEnum->Next(WBEM_INFINITE, 2, pObjs, &uCount)) )
  247. {
  248. //There should only be one result
  249. if (uCount == 1)
  250. {
  251. if (pObjs[0] != NULL)
  252. {
  253. *pInst = pObjs[0];
  254. retVal = TRUE;
  255. }
  256. else
  257. {
  258. if (pObjs[1] != NULL)
  259. {
  260. (pObjs[1])->Release();
  261. }
  262. }
  263. }
  264. else
  265. {
  266. if (pObjs[1] != NULL)
  267. {
  268. pObjs[1]->Release();
  269. if (pObjs[0] != NULL)
  270. {
  271. pObjs[0]->Release();
  272. }
  273. }
  274. }
  275. }
  276. }
  277. }
  278. pEnum->Release();
  279. }
  280. SysFreeString(queryLBStr);
  281. }
  282. delete [] tokArray;
  283. if (queryStr != NULL)
  284. {
  285. SysFreeString(queryStr);
  286. }
  287. return retVal;
  288. }
  289. //Get a view object given a source path
  290. BOOL HelperTaskObject::GetViewObject(const wchar_t* path, IWbemClassObject** pInst, CWbemServerWrap **a_ns)
  291. {
  292. if ((pInst == NULL) || (path == NULL) || (a_ns == NULL) || (*a_ns == NULL))
  293. {
  294. return FALSE;
  295. }
  296. else
  297. {
  298. *pInst = NULL;
  299. }
  300. CObjectPathParser objectPathParser;
  301. wchar_t* tmpPath = UnicodeStringDuplicate(path);
  302. ParsedObjectPath* parsedObjectPath = NULL;
  303. BOOL retVal = !objectPathParser.Parse(tmpPath, &parsedObjectPath);
  304. if (retVal && !parsedObjectPath->IsInstance())
  305. {
  306. retVal = FALSE;
  307. }
  308. if (retVal)
  309. {
  310. retVal = FALSE;
  311. if (Validate(NULL))
  312. {
  313. //try for all possible classes in namespaces that match
  314. //and return as soon as the first view instance is found...
  315. //==========================================================
  316. for (DWORD i = 0; (i < m_NSpaceArray.GetSize()) && (*pInst == NULL); i++)
  317. {
  318. CWbemServerWrap** t_pSrvs = m_NSpaceArray[i]->GetServerPtrs();
  319. CStringW* t_pathArray = m_NSpaceArray[i]->GetNamespacePaths();
  320. for (DWORD j = 0; (j < m_NSpaceArray[i]->GetCount()) && (*pInst == NULL); j++)
  321. {
  322. if (t_pSrvs[j] == NULL)
  323. {
  324. continue;
  325. }
  326. BOOL t_bCont = FALSE;
  327. //check that the servers match
  328. //=============================
  329. if ((parsedObjectPath->m_pServer == NULL) || (_wcsicmp(parsedObjectPath->m_pServer, L".") == 0))
  330. {
  331. if ((*a_ns)->IsRemote() && t_pSrvs[j]->IsRemote() &&
  332. (_wcsicmp((*a_ns)->GetPrincipal(), t_pSrvs[j]->GetPrincipal()) == 0))
  333. {
  334. t_bCont = TRUE;
  335. }
  336. else if (!(*a_ns)->IsRemote() && !t_pSrvs[j]->IsRemote())
  337. {
  338. t_bCont = TRUE;
  339. }
  340. }
  341. else
  342. {
  343. BOOL t_Local = bAreWeLocal(parsedObjectPath->m_pServer);
  344. if (t_Local && !t_pSrvs[j]->IsRemote())
  345. {
  346. t_bCont = TRUE;
  347. }
  348. else
  349. {
  350. if (t_pSrvs[j]->IsRemote())
  351. {
  352. if (_wcsicmp(t_pSrvs[j]->GetPrincipal(), parsedObjectPath->m_pServer) == 0)
  353. {
  354. t_bCont = TRUE;
  355. }
  356. else
  357. {
  358. DWORD t_len1 = wcslen(parsedObjectPath->m_pServer);
  359. DWORD t_len2 = wcslen(t_pSrvs[j]->GetPrincipal());
  360. if ((t_len2 > 0) && (t_len1 > 0) && (t_len1 < t_len2))
  361. {
  362. //machine.domain
  363. if ((_wcsnicmp(t_pSrvs[j]->GetPrincipal(), parsedObjectPath->m_pServer, t_len1) == 0) &&
  364. (((const wchar_t*)t_pSrvs[j]->GetPrincipal())[t_len1] == L'.'))
  365. {
  366. t_bCont = TRUE;
  367. }
  368. else
  369. {
  370. //could be the principal is domain\machine
  371. wchar_t *slash = wcschr(t_pSrvs[j]->GetPrincipal(), L'\\');
  372. if ((slash != NULL) && (_wcsicmp(parsedObjectPath->m_pServer, (slash+1)) == 0))
  373. {
  374. t_bCont = TRUE;
  375. }
  376. }
  377. }
  378. }
  379. }
  380. }
  381. }
  382. //check the namespace paths now
  383. //==============================
  384. if (t_bCont)
  385. {
  386. wchar_t *t_ns1 = parsedObjectPath->GetNamespacePart();
  387. BOOL t_bDel = TRUE;
  388. if (t_ns1 == NULL)
  389. {
  390. t_ns1 = (*a_ns)->GetPath();
  391. t_bDel = FALSE;
  392. }
  393. wchar_t *t_ns2 = t_pSrvs[j]->GetPath();
  394. if (!t_ns1 || !t_ns2)
  395. {
  396. t_bCont = FALSE;
  397. }
  398. else
  399. {
  400. //normalise...NOTE: no error checking since connection worked or parser worked
  401. //=============================================================================
  402. if (*t_ns1 == L'\\')
  403. {
  404. //skip the next slash
  405. t_ns1 += 2;
  406. while (*t_ns1 != L'\\')
  407. {
  408. t_ns1++;
  409. }
  410. t_ns1++;
  411. }
  412. if (*t_ns2 == L'\\')
  413. {
  414. //skip the next slash
  415. t_ns2 += 2;
  416. while (*t_ns2 != L'\\')
  417. {
  418. t_ns2++;
  419. }
  420. t_ns2++;
  421. }
  422. if (_wcsicmp(t_ns1, t_ns2) != 0)
  423. {
  424. t_bCont = FALSE;
  425. }
  426. }
  427. if (t_bDel && (t_ns1 != NULL))
  428. {
  429. delete [] t_ns1;
  430. }
  431. if (t_bCont)
  432. {
  433. //check that the class matches
  434. //=============================
  435. if (_wcsicmp(parsedObjectPath->m_pClass, m_SourceArray[i]->GetClassName()) == 0)
  436. {
  437. retVal = DoQuery(parsedObjectPath, pInst, j);
  438. break;
  439. }
  440. else
  441. {
  442. //uh-oh try classes derived from the source, i.e. do the query...
  443. //select * from meta_class where __this isa "m_SourceArray[i]->GetClassName()"
  444. // and __class = "parsedObjectPath->m_pClass"
  445. BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1);
  446. if (queryLBStr == NULL)
  447. {
  448. throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR);
  449. }
  450. BSTR queryBStr = SysAllocStringLen(NULL,
  451. 61 + wcslen(m_SourceArray[i]->GetClassName()) +
  452. wcslen(parsedObjectPath->m_pClass));
  453. if (queryBStr == NULL)
  454. {
  455. throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR);
  456. }
  457. wcscpy(queryBStr, META_CLASS_QUERY_START);
  458. wcscat(queryBStr, m_SourceArray[i]->GetClassName());
  459. wcscat(queryBStr, META_CLASS_QUERY_MID);
  460. wcscat(queryBStr, parsedObjectPath->m_pClass);
  461. wcscat(queryBStr, END_QUOTE);
  462. IWbemContext * t_pCtx = m_Ctx;
  463. if (t_pSrvs[j]->IsRemote())
  464. {
  465. t_pCtx = NULL; //don't use context for remote calls
  466. }
  467. IWbemServices *ptmpServ = t_pSrvs[j]->GetServerOrProxy();
  468. if (ptmpServ)
  469. {
  470. IEnumWbemClassObject *t_pEnum = NULL;
  471. HRESULT t_hr = ptmpServ->ExecQuery(queryLBStr, queryBStr, 0, t_pCtx, &t_pEnum);
  472. if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) &&
  473. t_pSrvs[j]->IsRemote())
  474. {
  475. if ( SUCCEEDED(UpdateConnection(&(t_pSrvs[j]), &ptmpServ)) )
  476. {
  477. if (ptmpServ)
  478. {
  479. t_hr = ptmpServ->ExecQuery(queryLBStr, queryBStr, 0,
  480. t_pCtx, &t_pEnum);
  481. }
  482. }
  483. }
  484. if (ptmpServ)
  485. {
  486. t_pSrvs[j]->ReturnServerOrProxy(ptmpServ);
  487. }
  488. if (SUCCEEDED(t_hr))
  489. {
  490. if (t_pSrvs[j]->IsRemote())
  491. {
  492. t_hr = SetSecurityLevelAndCloaking(t_pEnum,
  493. t_pSrvs[j]->GetPrincipal());
  494. }
  495. if (SUCCEEDED(t_hr))
  496. {
  497. //now use the enumerator and see if there is a result...
  498. IWbemClassObject* t_pClsObj = NULL;
  499. ULONG t_count = 0;
  500. //test each class in the derivation chain...
  501. if ( S_OK == t_pEnum->Next(WBEM_INFINITE, 1, &t_pClsObj, &t_count) )
  502. {
  503. if (t_pClsObj)
  504. {
  505. retVal = DoQuery(parsedObjectPath, pInst, j);
  506. t_pClsObj->Release();
  507. }
  508. }
  509. }
  510. t_pEnum->Release();
  511. }
  512. }
  513. }
  514. }
  515. }
  516. }
  517. }
  518. }
  519. }
  520. delete [] tmpPath;
  521. if (parsedObjectPath != NULL)
  522. {
  523. delete parsedObjectPath;
  524. }
  525. return retVal;
  526. }