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.

1769 lines
34 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation
  4. //
  5. // PATHCRAK.CPP
  6. //
  7. // alanbos 28-Mar-00 Created.
  8. //
  9. // Defines the implementation of CWbemPathCracker
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. //***************************************************************************
  14. //
  15. // CWbemPathCracker::CWbemPathCracker
  16. //
  17. // DESCRIPTION:
  18. //
  19. // Constructor.
  20. //
  21. //***************************************************************************
  22. CWbemPathCracker::CWbemPathCracker() :
  23. m_cRef (0),
  24. m_type (wbemPathTypeWmi)
  25. {
  26. InterlockedIncrement(&g_cObj);
  27. CreateParsers ();
  28. }
  29. //***************************************************************************
  30. //
  31. // CWbemPathCracker::CWbemPathCracker
  32. //
  33. // DESCRIPTION:
  34. //
  35. // Copy Constructor
  36. //
  37. //***************************************************************************
  38. CWbemPathCracker::CWbemPathCracker(CWbemPathCracker & pathCracker) :
  39. m_cRef (0),
  40. m_type (wbemPathTypeWmi)
  41. {
  42. InterlockedIncrement(&g_cObj);
  43. CreateParsers ();
  44. CComBSTR bsPath;
  45. if (pathCracker.GetPathText(bsPath, false, true))
  46. SetText (bsPath);
  47. }
  48. //***************************************************************************
  49. //
  50. // CWbemPathCracker::CWbemPathCracker
  51. //
  52. // DESCRIPTION:
  53. //
  54. // Constructor
  55. //
  56. //***************************************************************************
  57. CWbemPathCracker::CWbemPathCracker (const CComBSTR & bsPath) :
  58. m_pIWbemPath (NULL),
  59. m_cRef (0),
  60. m_type (wbemPathTypeWmi)
  61. {
  62. InterlockedIncrement(&g_cObj);
  63. CreateParsers ();
  64. SetText (bsPath);
  65. }
  66. //***************************************************************************
  67. //
  68. // CWbemPathCracker::~CWbemPathCracker
  69. //
  70. // DESCRIPTION:
  71. //
  72. // Destructor.
  73. //
  74. //***************************************************************************
  75. CWbemPathCracker::~CWbemPathCracker(void)
  76. {
  77. InterlockedDecrement(&g_cObj);
  78. }
  79. //***************************************************************************
  80. // HRESULT CWbemPathCracker::QueryInterface
  81. // long CWbemPathCracker::AddRef
  82. // long CWbemPathCracker::Release
  83. //
  84. // DESCRIPTION:
  85. //
  86. // Standard Com IUNKNOWN functions.
  87. //
  88. //***************************************************************************
  89. STDMETHODIMP CWbemPathCracker::QueryInterface (
  90. IN REFIID riid,
  91. OUT LPVOID *ppv
  92. )
  93. {
  94. *ppv=NULL;
  95. if (IID_IUnknown==riid)
  96. *ppv = (IUnknown*)(this);
  97. if (NULL!=*ppv)
  98. {
  99. ((LPUNKNOWN)*ppv)->AddRef();
  100. return NOERROR;
  101. }
  102. return ResultFromScode(E_NOINTERFACE);
  103. }
  104. STDMETHODIMP_(ULONG) CWbemPathCracker::AddRef(void)
  105. {
  106. InterlockedIncrement(&m_cRef);
  107. return m_cRef;
  108. }
  109. STDMETHODIMP_(ULONG) CWbemPathCracker::Release(void)
  110. {
  111. InterlockedDecrement(&m_cRef);
  112. if (0L!=m_cRef)
  113. return m_cRef;
  114. delete this;
  115. return 0;
  116. }
  117. void CWbemPathCracker::CreateParsers ()
  118. {
  119. m_pIWbemPath.Release ();
  120. CoCreateInstance (CLSID_WbemDefPath, NULL,
  121. CLSCTX_INPROC_SERVER, IID_IWbemPath, (PPVOID) &m_pIWbemPath);
  122. }
  123. void CWbemPathCracker::SetText (const CComBSTR & bsPath, bool bForceAsNamespace)
  124. {
  125. WbemPathType type = GetTypeFromText (bsPath);
  126. switch (type)
  127. {
  128. case wbemPathTypeWmi:
  129. {
  130. int iCreateFlags = WBEMPATH_CREATE_ACCEPT_ALL;
  131. // Check if we want single tokens to be interpreted as a namespace (e.g. "root")
  132. if (bForceAsNamespace)
  133. iCreateFlags |= WBEMPATH_TREAT_SINGLE_IDENT_AS_NS;
  134. if (m_pIWbemPath)
  135. {
  136. // The path parser should handle this, but doesn't!
  137. // If we have extracted this path from a V2-style reference
  138. // property it may be enclosed on "{" and "}". For now we strip
  139. // these off before parsing.
  140. if ((1 < bsPath.Length ()) && (L'{' == bsPath[0])
  141. && (L'}' == bsPath [bsPath.Length () -1]))
  142. {
  143. // Take off the first and last characters
  144. CComBSTR bsPath2 (bsPath + 1);
  145. bsPath2 [bsPath2.Length() - 1] = NULL;
  146. if (SUCCEEDED(m_pIWbemPath->SetText (iCreateFlags, bsPath2)))
  147. m_type = type;
  148. }
  149. else if (SUCCEEDED(m_pIWbemPath->SetText (iCreateFlags, bsPath)))
  150. m_type = type;
  151. }
  152. }
  153. break;
  154. case wbemPathTypeError:
  155. m_type = type;
  156. break;
  157. }
  158. }
  159. //***************************************************************************
  160. //
  161. // WbemPathType CWbemPathCracker::GetTypeFromText
  162. //
  163. // DESCRIPTION:
  164. //
  165. // Get the path type of the supplied string
  166. //
  167. // PARAMETERS:
  168. // bsPath the supplied string
  169. //
  170. // RETURN VALUES:
  171. // A WbemPathType
  172. //
  173. //***************************************************************************
  174. CWbemPathCracker::WbemPathType CWbemPathCracker::GetTypeFromText (
  175. const CComBSTR & bsPath
  176. )
  177. {
  178. WbemPathType type = wbemPathTypeError;
  179. // Try parsing it as a WMI path
  180. CComPtr<IWbemPath> pIWbemPath;
  181. if (SUCCEEDED(CoCreateInstance (CLSID_WbemDefPath, NULL,
  182. CLSCTX_INPROC_SERVER, IID_IWbemPath, (PPVOID) &pIWbemPath)))
  183. {
  184. if (SUCCEEDED(pIWbemPath->SetText (WBEMPATH_CREATE_ACCEPT_ALL, bsPath)))
  185. type = wbemPathTypeWmi;
  186. }
  187. return type;
  188. }
  189. //***************************************************************************
  190. //
  191. // bool CWbemPathCracker::GetPathText
  192. //
  193. // DESCRIPTION:
  194. //
  195. // Get the text of the path
  196. //
  197. // PARAMETERS:
  198. // bsPath the supplied string for holding the path
  199. // bRelativeOnly whether we only want the relpath
  200. // bIncludeServer whether to include the server
  201. // bNamespaceOnly whether we only want the namespace path
  202. //
  203. // RETURN VALUES:
  204. // true iff successful
  205. //
  206. //***************************************************************************
  207. bool CWbemPathCracker::GetPathText (
  208. CComBSTR & bsPath,
  209. bool bRelativeOnly,
  210. bool bIncludeServer,
  211. bool bNamespaceOnly
  212. )
  213. {
  214. bool result = false;
  215. switch (GetType ())
  216. {
  217. case wbemPathTypeWmi:
  218. {
  219. if (m_pIWbemPath)
  220. {
  221. ULONG lFlags = 0;
  222. if (bIncludeServer)
  223. lFlags |= WBEMPATH_GET_SERVER_TOO;
  224. else if (bRelativeOnly)
  225. lFlags |= WBEMPATH_GET_RELATIVE_ONLY;
  226. else if (bNamespaceOnly)
  227. lFlags |= WBEMPATH_GET_NAMESPACE_ONLY;
  228. // Find out our required buffer size
  229. ULONG lBuflen = 0;
  230. m_pIWbemPath->GetText (lFlags, &lBuflen, NULL);
  231. if (lBuflen)
  232. {
  233. LPWSTR pszText = new wchar_t [lBuflen + 1];
  234. if (pszText)
  235. {
  236. pszText [lBuflen] = NULL;
  237. if (SUCCEEDED(m_pIWbemPath->GetText (lFlags, &lBuflen, pszText)))
  238. {
  239. if (bsPath.m_str = SysAllocString (pszText))
  240. result = true;
  241. }
  242. delete [] pszText;
  243. }
  244. }
  245. else
  246. {
  247. // No text yet
  248. if (bsPath.m_str = SysAllocString (L""))
  249. result = true;
  250. }
  251. }
  252. }
  253. break;
  254. }
  255. return result;
  256. }
  257. //***************************************************************************
  258. //
  259. // bool CWbemPathCracker::operator =
  260. //
  261. // DESCRIPTION:
  262. //
  263. // Assigment operator
  264. //
  265. // PARAMETERS:
  266. // bsPath the supplied string
  267. //
  268. // RETURN VALUES:
  269. // A WbemPathType
  270. //
  271. //***************************************************************************
  272. bool CWbemPathCracker::operator = (const CComBSTR & bsPath)
  273. {
  274. bool result = false;
  275. // The parsers seem incapable of dealing with empty strings
  276. if (0 == bsPath.Length ())
  277. {
  278. CreateParsers ();
  279. result = true;
  280. }
  281. else
  282. {
  283. // Before we blat our object, check it.
  284. CWbemPathCracker pathCracker (bsPath);
  285. if (wbemPathTypeError != pathCracker.GetType ())
  286. {
  287. SetText (bsPath);
  288. result = true;
  289. }
  290. }
  291. return result;
  292. }
  293. const CWbemPathCracker & CWbemPathCracker::operator = (CWbemPathCracker & path)
  294. {
  295. CComBSTR bsPath;
  296. if (path.GetPathText (bsPath, false, true))
  297. *this = bsPath;
  298. return *this;
  299. }
  300. bool CWbemPathCracker::operator += (const CComBSTR & bsObjectPath)
  301. {
  302. return AddComponent (-1, bsObjectPath);
  303. }
  304. //***************************************************************************
  305. //
  306. // bool CWbemPathCracker::SetRelativePath
  307. //
  308. // DESCRIPTION:
  309. //
  310. // Set the relpath as a string
  311. //
  312. // PARAMETERS:
  313. // value new relpath
  314. //
  315. // RETURN VALUES:
  316. //
  317. // WBEM_S_NO_ERROR success
  318. // WBEM_E_INVALID_PARAMETER bad input parameters
  319. // WBEM_E_FAILED otherwise
  320. //
  321. //***************************************************************************
  322. bool CWbemPathCracker::SetRelativePath(
  323. const CComBSTR & bsRelPath
  324. )
  325. {
  326. bool result = false;
  327. // Parse the new path
  328. CWbemPathCracker pathCracker (bsRelPath);
  329. if (CopyServerAndNamespace (pathCracker))
  330. {
  331. *this = pathCracker;
  332. if (wbemPathTypeError != GetType())
  333. result = true;
  334. }
  335. return result;
  336. }
  337. //***************************************************************************
  338. //
  339. // bool CWbemPathCracker::CopyServerAndNamespace
  340. //
  341. // DESCRIPTION:
  342. //
  343. // Copy the server and namespace from this path to the
  344. // supplied path
  345. //
  346. // Note that it is assumed that the passed in path has no
  347. // namespace components.
  348. //
  349. // PARAMETERS:
  350. // pIWbemPath path into which info to be copied
  351. //
  352. // RETURN VALUES:
  353. //
  354. // WBEM_S_NO_ERROR success
  355. // WBEM_E_INVALID_PARAMETER bad input parameters
  356. // WBEM_E_FAILED otherwise
  357. //
  358. //***************************************************************************
  359. bool CWbemPathCracker::CopyServerAndNamespace (
  360. CWbemPathCracker &pathCracker
  361. )
  362. {
  363. bool result = false;
  364. CComBSTR bsServer;
  365. if (GetServer (bsServer) && pathCracker.SetServer (bsServer))
  366. {
  367. pathCracker.ClearNamespace ();
  368. ULONG lNsCount = 0;
  369. if (GetNamespaceCount (lNsCount))
  370. {
  371. bool ok = true;
  372. for (ULONG i = 0; (i < lNsCount) && ok; i++)
  373. {
  374. // Copy over this component
  375. CComBSTR bsNamespace;
  376. ok = GetNamespaceAt (i, bsNamespace) &&
  377. pathCracker.SetNamespaceAt (i, bsNamespace);
  378. }
  379. result = ok;
  380. }
  381. }
  382. return result;
  383. }
  384. //***************************************************************************
  385. //
  386. // bool CWbemPathCracker::GetNamespaceAt
  387. //
  388. // DESCRIPTION:
  389. //
  390. // Copy the server and namespace from this path to the
  391. // supplied path
  392. //
  393. // Note that it is assumed that the passed in path has no
  394. // namespace components.
  395. //
  396. // PARAMETERS:
  397. // pIWbemPath path into which info to be copied
  398. //
  399. // RETURN VALUES:
  400. //
  401. // WBEM_S_NO_ERROR success
  402. // WBEM_E_INVALID_PARAMETER bad input parameters
  403. // WBEM_E_FAILED otherwise
  404. //
  405. //***************************************************************************
  406. bool CWbemPathCracker::GetNamespaceAt (
  407. ULONG iIndex,
  408. CComBSTR & bsPath
  409. )
  410. {
  411. bool result = false;
  412. switch (GetType ())
  413. {
  414. case wbemPathTypeWmi:
  415. {
  416. if (m_pIWbemPath)
  417. {
  418. ULONG lBufLen = 0;
  419. m_pIWbemPath->GetNamespaceAt (iIndex, &lBufLen, NULL);
  420. wchar_t *pszText = new wchar_t [lBufLen + 1];
  421. if (pszText)
  422. {
  423. pszText [lBufLen] = NULL;
  424. if (SUCCEEDED(m_pIWbemPath->GetNamespaceAt (iIndex, &lBufLen, pszText)))
  425. {
  426. if (bsPath.m_str = SysAllocString (pszText))
  427. result = true;
  428. }
  429. delete [] pszText;
  430. }
  431. }
  432. }
  433. break;
  434. }
  435. return result;
  436. }
  437. bool CWbemPathCracker::SetNamespaceAt (
  438. ULONG iIndex,
  439. const CComBSTR & bsPath
  440. )
  441. {
  442. bool result = false;
  443. switch (GetType ())
  444. {
  445. case wbemPathTypeWmi:
  446. {
  447. if (m_pIWbemPath)
  448. {
  449. if (SUCCEEDED(m_pIWbemPath->SetNamespaceAt (iIndex, bsPath)))
  450. result = true;
  451. }
  452. }
  453. break;
  454. }
  455. return result;
  456. }
  457. //***************************************************************************
  458. //
  459. // bool CWbemPathCracker::GetServer
  460. //
  461. // DESCRIPTION:
  462. //
  463. // Get the server name as a string
  464. //
  465. // PARAMETERS:
  466. // value pointer to BSTR value returned
  467. //
  468. // RETURN VALUES:
  469. //
  470. // WBEM_S_NO_ERROR success
  471. // WBEM_E_INVALID_PARAMETER bad input parameters
  472. // WBEM_E_FAILED otherwise
  473. //
  474. //***************************************************************************
  475. bool CWbemPathCracker::GetServer (
  476. CComBSTR & bsPath
  477. )
  478. {
  479. bool result = false;
  480. switch (GetType ())
  481. {
  482. case wbemPathTypeWmi:
  483. {
  484. if (m_pIWbemPath)
  485. {
  486. ULONG lBufLen = 0;
  487. m_pIWbemPath->GetServer (&lBufLen, NULL);
  488. if (lBufLen)
  489. {
  490. wchar_t *pszText = new wchar_t [lBufLen + 1];
  491. if (pszText)
  492. {
  493. pszText [lBufLen] = NULL;
  494. if (SUCCEEDED(m_pIWbemPath->GetServer (&lBufLen, pszText)))
  495. {
  496. if (bsPath.m_str = SysAllocString (pszText))
  497. result = true;
  498. }
  499. delete [] pszText;
  500. }
  501. }
  502. else
  503. {
  504. // No server component yet
  505. if (bsPath.m_str = SysAllocString (L""))
  506. result = true;
  507. }
  508. }
  509. }
  510. break;
  511. }
  512. return result;
  513. }
  514. //***************************************************************************
  515. //
  516. // bool CWbemPathCracker::SetServer
  517. //
  518. // DESCRIPTION:
  519. //
  520. // Set the server name as a string
  521. //
  522. // PARAMETERS:
  523. // value new server name
  524. //
  525. // RETURN VALUES:
  526. //
  527. // WBEM_S_NO_ERROR success
  528. // WBEM_E_INVALID_PARAMETER bad input parameters
  529. // WBEM_E_FAILED otherwise
  530. //
  531. //***************************************************************************
  532. bool CWbemPathCracker::SetServer(
  533. const CComBSTR & bsPath
  534. )
  535. {
  536. bool result = false;
  537. switch (GetType ())
  538. {
  539. case wbemPathTypeWmi:
  540. {
  541. if (m_pIWbemPath)
  542. {
  543. /*
  544. * The observant reader will notice we check for an empty path and
  545. * transform it to a NULL. This is to defensively code against behavior
  546. * in the parsers which actually treat an empty server path as NOT
  547. * being equivalent to NULL.
  548. */
  549. if (0 < bsPath.Length())
  550. result = SUCCEEDED(m_pIWbemPath->SetServer (bsPath));
  551. else
  552. result = SUCCEEDED(m_pIWbemPath->SetServer (NULL));
  553. }
  554. }
  555. break;
  556. }
  557. return result;
  558. }
  559. //***************************************************************************
  560. //
  561. // bool CWbemPathCracker::GetNamespacePath
  562. //
  563. // DESCRIPTION:
  564. //
  565. // Get the namespace path (excluding server) as a string
  566. //
  567. // PARAMETERS:
  568. // value pointer to BSTR value returned
  569. // bParentOnly whether to strip off leaf namespace
  570. //
  571. // RETURN VALUES:
  572. //
  573. // WBEM_S_NO_ERROR success
  574. // WBEM_E_INVALID_PARAMETER bad input parameters
  575. // WBEM_E_FAILED otherwise
  576. //
  577. //***************************************************************************
  578. bool CWbemPathCracker::GetNamespacePath(
  579. CComBSTR & bsPath,
  580. bool bParentOnly)
  581. {
  582. bool result = false;
  583. // Build up the namespace value
  584. ULONG lNsCount = 0;
  585. if (GetNamespaceCount (lNsCount))
  586. {
  587. if ((bParentOnly && (1 < lNsCount)) || (!bParentOnly && (0 < lNsCount)))
  588. {
  589. // Get the full path and remove the server and objectref pieces
  590. CComBSTR bsNamespacePath;
  591. if (GetPathText (bsNamespacePath, false, false, true))
  592. {
  593. wchar_t *ptrStart = bsNamespacePath;
  594. if (IsClassOrInstance ())
  595. {
  596. // We have an object ref so look for the first ":"
  597. wchar_t *ptrEnd = wcschr (ptrStart, L':');
  598. if (ptrEnd)
  599. *ptrEnd = NULL;
  600. }
  601. // Getting here means we have just the namespace path left
  602. // in ptrStart. Final step is to possibly remove the last
  603. // component
  604. if (bParentOnly)
  605. {
  606. wchar_t *ptrEnd = NULL;
  607. wchar_t *ptrEnd1 = wcsrchr (ptrStart, L'/');
  608. wchar_t *ptrEnd2 = wcsrchr (ptrStart, L'\\');
  609. if (ptrEnd1 && ptrEnd2)
  610. ptrEnd = (ptrEnd1 < ptrEnd2) ? ptrEnd2 : ptrEnd1;
  611. else if (!ptrEnd1 && ptrEnd2)
  612. ptrEnd = ptrEnd2;
  613. else if (ptrEnd1 && !ptrEnd2)
  614. ptrEnd = ptrEnd1;
  615. if (ptrEnd)
  616. *ptrEnd = NULL;
  617. }
  618. bsPath.m_str = SysAllocString (ptrStart);
  619. result = true;
  620. }
  621. }
  622. else
  623. {
  624. // Degenerate case - no namespace portion
  625. bsPath.m_str = SysAllocString (L"");
  626. result = true;
  627. }
  628. }
  629. return result;
  630. }
  631. bool CWbemPathCracker::IsClassOrInstance ()
  632. {
  633. return (IsClass () || IsInstance ());
  634. }
  635. //***************************************************************************
  636. //
  637. // bool CWbemPathCracker::SetNamespacePath
  638. //
  639. // DESCRIPTION:
  640. //
  641. // Put the namespace as a string
  642. //
  643. // PARAMETERS:
  644. // bsPath new namespace path
  645. //
  646. // RETURN VALUES:
  647. //
  648. // WBEM_S_NO_ERROR success
  649. // WBEM_E_INVALID_PARAMETER bad input parameters
  650. // WBEM_E_FAILED otherwise
  651. //
  652. //***************************************************************************
  653. bool CWbemPathCracker::SetNamespacePath (
  654. const CComBSTR & bsPath
  655. )
  656. {
  657. bool result = false;
  658. switch (GetType ())
  659. {
  660. case wbemPathTypeWmi:
  661. {
  662. if (m_pIWbemPath)
  663. {
  664. CWbemPathCracker newPath;
  665. newPath.SetText (bsPath, true);
  666. if(wbemPathTypeError != newPath.GetType ())
  667. {
  668. // Copy the namespace info into our current path
  669. unsigned long lNsCount = 0;
  670. if (newPath.GetNamespaceCount (lNsCount))
  671. {
  672. // Scratch the old namespace part
  673. ClearNamespace ();
  674. if (0 < lNsCount)
  675. {
  676. // Fill in using the new part
  677. bool ok = true;
  678. for (ULONG i = 0; (i <lNsCount) && ok; i++)
  679. {
  680. CComBSTR bsNs;
  681. if (!(newPath.GetNamespaceAt (i, bsNs)) ||
  682. FAILED(m_pIWbemPath->SetNamespaceAt (i, bsNs)))
  683. ok = false;
  684. }
  685. if (ok)
  686. result = true;
  687. }
  688. }
  689. }
  690. }
  691. }
  692. break;
  693. }
  694. return result;
  695. }
  696. bool CWbemPathCracker::GetNamespaceCount (
  697. unsigned long & lCount
  698. )
  699. {
  700. bool result = false;
  701. switch (GetType ())
  702. {
  703. case wbemPathTypeWmi:
  704. {
  705. if (m_pIWbemPath)
  706. if (SUCCEEDED(m_pIWbemPath->GetNamespaceCount (&lCount)))
  707. result = true;
  708. }
  709. break;
  710. }
  711. return result;
  712. }
  713. bool CWbemPathCracker::RemoveNamespace (
  714. ULONG iIndex
  715. )
  716. {
  717. bool result = false;
  718. switch (GetType ())
  719. {
  720. case wbemPathTypeWmi:
  721. {
  722. if (m_pIWbemPath)
  723. if (SUCCEEDED(m_pIWbemPath->RemoveNamespaceAt (iIndex)))
  724. result = true;
  725. }
  726. break;
  727. }
  728. return result;
  729. }
  730. void CWbemPathCracker::ClearNamespace()
  731. {
  732. switch (GetType ())
  733. {
  734. case wbemPathTypeWmi:
  735. {
  736. if (m_pIWbemPath)
  737. m_pIWbemPath->RemoveAllNamespaces ();
  738. }
  739. break;
  740. }
  741. }
  742. //***************************************************************************
  743. //
  744. // bool CWbemPathCracker::IsClass
  745. //
  746. // DESCRIPTION:
  747. //
  748. // Get whether the path is to a class
  749. //
  750. // PARAMETERS:
  751. // value pointer to BSTR value returned
  752. //
  753. // RETURN VALUES:
  754. //
  755. // WBEM_S_NO_ERROR success
  756. // WBEM_E_INVALID_PARAMETER bad input parameters
  757. // WBEM_E_FAILED otherwise
  758. //
  759. //***************************************************************************
  760. bool CWbemPathCracker::IsClass ()
  761. {
  762. bool result = false;
  763. switch (GetType ())
  764. {
  765. case wbemPathTypeWmi:
  766. {
  767. if (m_pIWbemPath)
  768. {
  769. ULONGLONG lInfo = 0;
  770. if (SUCCEEDED(m_pIWbemPath->GetInfo (0 /*WBEMPATH_INFO_IS_CLASS_REF*/, &lInfo)))
  771. result = (WBEMPATH_INFO_IS_CLASS_REF & lInfo) ? true : false;
  772. }
  773. }
  774. break;
  775. }
  776. return result;
  777. }
  778. bool CWbemPathCracker::IsSingleton ()
  779. {
  780. bool result = false;
  781. switch (GetType ())
  782. {
  783. case wbemPathTypeWmi:
  784. {
  785. if (m_pIWbemPath)
  786. {
  787. ULONGLONG lInfo = 0;
  788. if (SUCCEEDED(m_pIWbemPath->GetInfo (0 /*WBEMPATH_INFO_IS_SINGLETON*/, &lInfo)))
  789. result = (WBEMPATH_INFO_IS_SINGLETON & lInfo) ? true : false;
  790. }
  791. }
  792. break;
  793. }
  794. return result;
  795. }
  796. bool CWbemPathCracker::IsInstance ()
  797. {
  798. bool result = false;
  799. switch (GetType ())
  800. {
  801. case wbemPathTypeWmi:
  802. {
  803. if (m_pIWbemPath)
  804. {
  805. ULONGLONG lInfo = 0;
  806. if (SUCCEEDED(m_pIWbemPath->GetInfo (0 /*WBEMPATH_INFO_IS_CLASS_REF*/, &lInfo)))
  807. result = (WBEMPATH_INFO_IS_INST_REF & lInfo) ? true : false;
  808. }
  809. }
  810. break;
  811. }
  812. return result;
  813. }
  814. //***************************************************************************
  815. //
  816. // bool CWbemPathCracker::SetAsClass
  817. //
  818. // DESCRIPTION:
  819. //
  820. // Set the path as a class path
  821. //
  822. // PARAMETERS:
  823. // none
  824. //
  825. // RETURN VALUES:
  826. //
  827. // WBEM_S_NO_ERROR success
  828. // WBEM_E_INVALID_PARAMETER bad input parameters
  829. // WBEM_E_FAILED otherwise
  830. //
  831. //***************************************************************************
  832. bool CWbemPathCracker::SetAsClass()
  833. {
  834. return ClearKeys ();
  835. }
  836. //***************************************************************************
  837. //
  838. // bool CWbemPathCracker::SetAsSingleton
  839. //
  840. // DESCRIPTION:
  841. //
  842. // Set the path as a singleton instance path
  843. //
  844. // PARAMETERS:
  845. // none
  846. //
  847. // RETURN VALUES:
  848. //
  849. // WBEM_S_NO_ERROR success
  850. // WBEM_E_INVALID_PARAMETER bad input parameters
  851. // WBEM_E_FAILED otherwise
  852. //
  853. //***************************************************************************
  854. bool CWbemPathCracker::SetAsSingleton()
  855. {
  856. return ClearKeys (false);
  857. }
  858. //***************************************************************************
  859. //
  860. // SCODE CWbemPathCracker::get_Class
  861. //
  862. // DESCRIPTION:
  863. //
  864. // Get the class name from the path
  865. //
  866. // PARAMETERS:
  867. // value pointer to BSTR value returned
  868. //
  869. // RETURN VALUES:
  870. //
  871. // WBEM_S_NO_ERROR success
  872. // WBEM_E_INVALID_PARAMETER bad input parameters
  873. // WBEM_E_FAILED otherwise
  874. //
  875. //***************************************************************************
  876. bool CWbemPathCracker::GetClass (
  877. CComBSTR & bsPath
  878. )
  879. {
  880. bool result = false;
  881. switch (GetType ())
  882. {
  883. case wbemPathTypeWmi:
  884. {
  885. if (m_pIWbemPath)
  886. {
  887. ULONG lBufLen = 0;
  888. m_pIWbemPath->GetClassName (&lBufLen, NULL);
  889. if (lBufLen)
  890. {
  891. wchar_t *pszText = new wchar_t [lBufLen + 1];
  892. if (pszText)
  893. {
  894. pszText [lBufLen] = NULL;
  895. if (SUCCEEDED(m_pIWbemPath->GetClassName (&lBufLen, pszText)))
  896. {
  897. if (bsPath.m_str = SysAllocString (pszText))
  898. result = true;
  899. }
  900. delete [] pszText;
  901. }
  902. }
  903. else
  904. {
  905. // No class defined yet
  906. if (bsPath.m_str = SysAllocString (L""))
  907. result = true;
  908. }
  909. }
  910. }
  911. break;
  912. }
  913. return result;
  914. }
  915. bool CWbemPathCracker::GetComponent (
  916. ULONG iIndex,
  917. CComBSTR & bsPath
  918. )
  919. {
  920. bool result = false;
  921. switch (GetType ())
  922. {
  923. case wbemPathTypeWmi:
  924. {
  925. if (m_pIWbemPath)
  926. {
  927. ULONG lScopeCount = 0;
  928. if (SUCCEEDED(m_pIWbemPath->GetScopeCount (&lScopeCount)))
  929. {
  930. if (-1 == iIndex)
  931. iIndex = lScopeCount - 1;
  932. if (iIndex < lScopeCount)
  933. {
  934. ULONG lBufLen = 0;
  935. m_pIWbemPath->GetScopeAsText (iIndex, &lBufLen, NULL);
  936. wchar_t *pszText = new wchar_t [lBufLen + 1];
  937. if (pszText)
  938. {
  939. pszText [lBufLen] = NULL;
  940. if (SUCCEEDED(m_pIWbemPath->GetScopeAsText (iIndex, &lBufLen, pszText)))
  941. {
  942. if (bsPath.m_str = SysAllocString (pszText))
  943. result = true;
  944. }
  945. delete [] pszText;
  946. }
  947. }
  948. }
  949. }
  950. }
  951. break;
  952. }
  953. return result;
  954. }
  955. //***************************************************************************
  956. //
  957. // SCODE CSWbemObjectPath::SetClass
  958. //
  959. // DESCRIPTION:
  960. //
  961. // Set the class name in the path
  962. //
  963. // PARAMETERS:
  964. // value new class name
  965. //
  966. // RETURN VALUES:
  967. //
  968. // WBEM_S_NO_ERROR success
  969. // WBEM_E_INVALID_PARAMETER bad input parameters
  970. // WBEM_E_FAILED otherwise
  971. //
  972. //***************************************************************************
  973. bool CWbemPathCracker::SetClass(
  974. const CComBSTR & bsClass)
  975. {
  976. bool result = false;
  977. switch (GetType ())
  978. {
  979. case wbemPathTypeWmi:
  980. {
  981. if (m_pIWbemPath)
  982. {
  983. if (SUCCEEDED(m_pIWbemPath->SetClassName (bsClass)))
  984. result = true;
  985. }
  986. }
  987. break;
  988. }
  989. return result;
  990. }
  991. //***************************************************************************
  992. //
  993. // SCODE CSWbemObjectPath::get_Keys
  994. //
  995. // DESCRIPTION:
  996. //
  997. // Get the keys collection from the path
  998. //
  999. // PARAMETERS:
  1000. // objKeys pointer to ISWbemNamedValueSet returned
  1001. //
  1002. // RETURN VALUES:
  1003. //
  1004. // WBEM_S_NO_ERROR success
  1005. // WBEM_E_INVALID_PARAMETER bad input parameters
  1006. // WBEM_E_FAILED otherwise
  1007. //
  1008. //***************************************************************************
  1009. bool CWbemPathCracker::GetKeys(
  1010. ISWbemNamedValueSet **objKeys
  1011. )
  1012. {
  1013. bool result = false;
  1014. if (objKeys)
  1015. {
  1016. *objKeys = NULL;
  1017. CSWbemNamedValueSet *pCSWbemNamedValueSet = new CSWbemNamedValueSet (this);
  1018. if (pCSWbemNamedValueSet)
  1019. {
  1020. if (SUCCEEDED(pCSWbemNamedValueSet->QueryInterface (IID_ISWbemNamedValueSet,
  1021. (PPVOID) objKeys)))
  1022. result = true;
  1023. else
  1024. delete pCSWbemNamedValueSet;
  1025. }
  1026. }
  1027. return result;
  1028. }
  1029. bool CWbemPathCracker::SetKey (
  1030. const CComBSTR & bsName,
  1031. WbemCimtypeEnum cimType,
  1032. VARIANT &var
  1033. )
  1034. {
  1035. bool result = false;
  1036. switch (GetType ())
  1037. {
  1038. case wbemPathTypeWmi:
  1039. {
  1040. if (m_pIWbemPath)
  1041. {
  1042. CComPtr<IWbemPathKeyList> pIWbemPathKeyList;
  1043. if (SUCCEEDED(m_pIWbemPath->GetKeyList (&pIWbemPathKeyList))
  1044. && SUCCEEDED(pIWbemPathKeyList->SetKey2 (bsName, 0, cimType, &var)))
  1045. result = true;
  1046. }
  1047. }
  1048. break;
  1049. }
  1050. return result;
  1051. }
  1052. bool CWbemPathCracker::GetKeyCount (
  1053. ULONG & iCount
  1054. )
  1055. {
  1056. bool result = false;
  1057. switch (GetType ())
  1058. {
  1059. case wbemPathTypeWmi:
  1060. {
  1061. if (m_pIWbemPath)
  1062. {
  1063. CComPtr<IWbemPathKeyList> pIWbemPathKeyList;
  1064. iCount = 0;
  1065. if (FAILED(m_pIWbemPath->GetKeyList (&pIWbemPathKeyList))
  1066. || SUCCEEDED(pIWbemPathKeyList->GetCount (&iCount)))
  1067. result = true;
  1068. }
  1069. }
  1070. break;
  1071. }
  1072. return result;
  1073. }
  1074. bool CWbemPathCracker::RemoveAllKeys ()
  1075. {
  1076. bool result = false;
  1077. switch (GetType ())
  1078. {
  1079. case wbemPathTypeWmi:
  1080. {
  1081. if (m_pIWbemPath)
  1082. {
  1083. CComPtr<IWbemPathKeyList> pIWbemPathKeyList;
  1084. if (FAILED(m_pIWbemPath->GetKeyList (&pIWbemPathKeyList))
  1085. || SUCCEEDED(pIWbemPathKeyList->RemoveAllKeys (0)))
  1086. result = true;
  1087. }
  1088. }
  1089. break;
  1090. }
  1091. return result;
  1092. }
  1093. bool CWbemPathCracker::RemoveKey (
  1094. const CComBSTR &bsName
  1095. )
  1096. {
  1097. bool result = false;
  1098. switch (GetType ())
  1099. {
  1100. case wbemPathTypeWmi:
  1101. {
  1102. if (m_pIWbemPath)
  1103. {
  1104. CComPtr<IWbemPathKeyList> pIWbemPathKeyList;
  1105. if (FAILED(m_pIWbemPath->GetKeyList (&pIWbemPathKeyList))
  1106. || SUCCEEDED(pIWbemPathKeyList->RemoveKey (bsName, 0)))
  1107. result = true;
  1108. }
  1109. }
  1110. break;
  1111. }
  1112. return result;
  1113. }
  1114. bool CWbemPathCracker::GetComponentCount (
  1115. ULONG & iCount
  1116. )
  1117. {
  1118. bool result = false;
  1119. switch (GetType ())
  1120. {
  1121. case wbemPathTypeWmi:
  1122. {
  1123. if (m_pIWbemPath)
  1124. result = SUCCEEDED(m_pIWbemPath->GetScopeCount (&iCount));
  1125. }
  1126. break;
  1127. }
  1128. return result;
  1129. }
  1130. bool CWbemPathCracker::AddComponent (
  1131. ULONG iIndex,
  1132. const CComBSTR & bsComponent
  1133. )
  1134. {
  1135. bool result = false;
  1136. ULONG lComponentCount = 0;
  1137. if (GetComponentCount (lComponentCount))
  1138. {
  1139. if (-1 == iIndex)
  1140. iIndex = lComponentCount;
  1141. if (iIndex <= lComponentCount)
  1142. {
  1143. switch (GetType ())
  1144. {
  1145. case wbemPathTypeWmi:
  1146. {
  1147. if (m_pIWbemPath)
  1148. {
  1149. if (iIndex < lComponentCount)
  1150. {
  1151. // need to do an insertion - we will have to move
  1152. // all subsequent elements up by one
  1153. for (ULONG i = lComponentCount-1; i >= iIndex; i--)
  1154. {
  1155. ULONG lBufLen = 0;
  1156. m_pIWbemPath->GetScopeAsText (iIndex, &lBufLen, NULL);
  1157. wchar_t *pszText = new wchar_t [lBufLen + 1];
  1158. if (pszText)
  1159. {
  1160. pszText [lBufLen] = NULL;
  1161. if (SUCCEEDED(m_pIWbemPath->GetScopeAsText (i, &lBufLen, pszText)))
  1162. m_pIWbemPath->SetScopeFromText (i + 1, pszText);
  1163. delete [] pszText;
  1164. }
  1165. }
  1166. if (SUCCEEDED(m_pIWbemPath->SetScopeFromText (iIndex, bsComponent)))
  1167. result = true;
  1168. }
  1169. else
  1170. {
  1171. // just add it to the end
  1172. if (SUCCEEDED(m_pIWbemPath->SetScopeFromText (iIndex, bsComponent)))
  1173. result = true;
  1174. }
  1175. }
  1176. }
  1177. break;
  1178. }
  1179. }
  1180. }
  1181. return result;
  1182. }
  1183. bool CWbemPathCracker::SetComponent (
  1184. ULONG iIndex,
  1185. const CComBSTR & bsComponent
  1186. )
  1187. {
  1188. bool result = false;
  1189. ULONG lComponentCount = 0;
  1190. if (GetComponentCount (lComponentCount) & (0 < lComponentCount))
  1191. {
  1192. if (-1 == iIndex)
  1193. iIndex = lComponentCount - 1;
  1194. // Is our index in range
  1195. if (iIndex < lComponentCount)
  1196. {
  1197. switch (GetType ())
  1198. {
  1199. case wbemPathTypeWmi:
  1200. {
  1201. if (m_pIWbemPath)
  1202. {
  1203. if (SUCCEEDED(m_pIWbemPath->SetScopeFromText (iIndex, bsComponent)))
  1204. result = true;
  1205. }
  1206. }
  1207. break;
  1208. }
  1209. }
  1210. }
  1211. return result;
  1212. }
  1213. bool CWbemPathCracker::RemoveComponent (
  1214. ULONG iIndex
  1215. )
  1216. {
  1217. bool result = false;
  1218. ULONG lComponentCount = 0;
  1219. if (GetComponentCount (lComponentCount) & (0 < lComponentCount))
  1220. {
  1221. if (-1 == iIndex)
  1222. iIndex = lComponentCount - 1;
  1223. // Is our index in range
  1224. if (iIndex < lComponentCount)
  1225. {
  1226. switch (GetType ())
  1227. {
  1228. case wbemPathTypeWmi:
  1229. {
  1230. if (m_pIWbemPath)
  1231. {
  1232. if (SUCCEEDED(m_pIWbemPath->RemoveScope (iIndex)))
  1233. result = true;
  1234. }
  1235. }
  1236. break;
  1237. }
  1238. }
  1239. }
  1240. return result;
  1241. }
  1242. bool CWbemPathCracker::RemoveAllComponents ()
  1243. {
  1244. bool result = false;
  1245. switch (GetType ())
  1246. {
  1247. case wbemPathTypeWmi:
  1248. {
  1249. if (m_pIWbemPath)
  1250. {
  1251. if (SUCCEEDED(m_pIWbemPath->RemoveAllScopes ()))
  1252. result = true;
  1253. }
  1254. }
  1255. break;
  1256. }
  1257. return result;
  1258. }
  1259. //***************************************************************************
  1260. //
  1261. // SCODE CSWbemObjectPath::GetParent
  1262. //
  1263. // DESCRIPTION:
  1264. //
  1265. // Get the parent path
  1266. //
  1267. // PARAMETERS:
  1268. // ppISWbemObjectPath - parent path on return
  1269. //
  1270. // RETURN VALUES:
  1271. //
  1272. // WBEM_S_NO_ERROR success
  1273. // WBEM_E_INVALID_PARAMETER bad input parameters
  1274. // WBEM_E_FAILED otherwise
  1275. //
  1276. //***************************************************************************
  1277. bool CWbemPathCracker::GetParent(
  1278. CWbemPathCracker & pathCracker)
  1279. {
  1280. pathCracker = *this;
  1281. return pathCracker.SetAsParent ();
  1282. }
  1283. bool CWbemPathCracker::SetAsParent ()
  1284. {
  1285. bool result = false;
  1286. ULONG lComponents;
  1287. if (GetComponentCount (lComponents))
  1288. {
  1289. if (0 == lComponents)
  1290. {
  1291. // No components - do we have any Namespaces
  1292. ULONG lNamespaces = 0;
  1293. if (GetNamespaceCount (lNamespaces))
  1294. {
  1295. if (0 == lNamespaces)
  1296. {
  1297. // No namespace - do nothing
  1298. result = true;
  1299. }
  1300. else
  1301. result = RemoveNamespace (lNamespaces-1);
  1302. }
  1303. }
  1304. else
  1305. {
  1306. // Remove the last component
  1307. result = RemoveComponent (-1);
  1308. }
  1309. }
  1310. return result;
  1311. }
  1312. //***************************************************************************
  1313. //
  1314. // bool CWbemPathCracker::ClearKeys
  1315. //
  1316. // DESCRIPTION:
  1317. //
  1318. // Zap the keys from the path parser
  1319. //
  1320. // PARAMETERS:
  1321. // none
  1322. //
  1323. // RETURN VALUES:
  1324. //
  1325. // WBEM_S_NO_ERROR success
  1326. //
  1327. //***************************************************************************
  1328. bool CWbemPathCracker::ClearKeys (bool bTreatAsClass)
  1329. {
  1330. bool result = false;
  1331. switch (GetType ())
  1332. {
  1333. case wbemPathTypeWmi:
  1334. {
  1335. if (m_pIWbemPath)
  1336. {
  1337. CComPtr<IWbemPathKeyList> pIWbemPathKeyList;
  1338. if (SUCCEEDED(m_pIWbemPath->GetKeyList (&pIWbemPathKeyList)))
  1339. {
  1340. if (SUCCEEDED(pIWbemPathKeyList->RemoveAllKeys (0)))
  1341. {
  1342. if (SUCCEEDED(pIWbemPathKeyList->MakeSingleton ((bTreatAsClass) ? FALSE : TRUE)))
  1343. result = true;
  1344. }
  1345. }
  1346. else
  1347. {
  1348. // If no keys, we assume this is done.
  1349. result = true;
  1350. }
  1351. }
  1352. }
  1353. break;
  1354. }
  1355. return result;
  1356. }
  1357. bool CWbemPathCracker::GetKey (
  1358. ULONG iIndex,
  1359. CComBSTR &bsName,
  1360. VARIANT &var,
  1361. WbemCimtypeEnum &cimType
  1362. )
  1363. {
  1364. bool result = false;
  1365. switch (GetType ())
  1366. {
  1367. case wbemPathTypeWmi:
  1368. {
  1369. if (m_pIWbemPath)
  1370. {
  1371. CComPtr<IWbemPathKeyList> pIWbemPathKeyList;
  1372. if (SUCCEEDED(m_pIWbemPath->GetKeyList (&pIWbemPathKeyList)))
  1373. {
  1374. if (pIWbemPathKeyList)
  1375. {
  1376. ULONG lBufLen = 0;
  1377. ULONG lCimType;
  1378. pIWbemPathKeyList->GetKey2 (iIndex, 0, &lBufLen, NULL, &var, &lCimType);
  1379. wchar_t *pszText = new wchar_t [lBufLen + 1];
  1380. if (pszText)
  1381. {
  1382. pszText [lBufLen] = NULL;
  1383. if (SUCCEEDED(pIWbemPathKeyList->GetKey2 (iIndex, 0, &lBufLen, pszText,
  1384. &var, &lCimType)))
  1385. {
  1386. bsName.m_str = SysAllocString (pszText);
  1387. cimType = (WbemCimtypeEnum) lCimType;
  1388. result = true;
  1389. }
  1390. delete [] pszText;
  1391. }
  1392. }
  1393. }
  1394. }
  1395. }
  1396. break;
  1397. }
  1398. return result;
  1399. }
  1400. static bool KeyMatch (CComVariant & var1, CComVariant & var2)
  1401. {
  1402. bool keyMatch = false;
  1403. if (var1 == var2)
  1404. keyMatch = true;
  1405. else
  1406. {
  1407. // Check for string key values that are case-insensitive
  1408. if ((var1.vt == var2.vt) && (VT_BSTR == var1.vt))
  1409. keyMatch = var1.bstrVal && var2.bstrVal &&
  1410. (0 == _wcsicmp (var1.bstrVal,
  1411. var2.bstrVal));
  1412. }
  1413. return keyMatch;
  1414. }
  1415. bool CWbemPathCracker::operator == (const CComBSTR & path)
  1416. {
  1417. bool result = false;
  1418. CWbemPathCracker otherPath (path);
  1419. if (GetType () == otherPath.GetType ())
  1420. {
  1421. switch (GetType ())
  1422. {
  1423. case wbemPathTypeWmi:
  1424. {
  1425. if (IsClassOrInstance () && otherPath.IsClassOrInstance ())
  1426. {
  1427. // Do we have matching class names?
  1428. CComBSTR thisClass, otherClass;
  1429. if (GetClass (thisClass) && (otherPath.GetClass (otherClass))
  1430. && (0 == _wcsicmp (thisClass, otherClass)))
  1431. {
  1432. // Are they both singletons?
  1433. if (IsSingleton () == otherPath.IsSingleton ())
  1434. {
  1435. if (IsSingleton ())
  1436. {
  1437. result = true;
  1438. }
  1439. else if (IsClass () && otherPath.IsClass ())
  1440. {
  1441. result = true;
  1442. }
  1443. else if (IsInstance () && otherPath.IsInstance ())
  1444. {
  1445. // Now we need to keymatch
  1446. ULONG thisKeyCount, otherKeyCount;
  1447. if (GetKeyCount (thisKeyCount) && otherPath.GetKeyCount (otherKeyCount)
  1448. && (thisKeyCount == otherKeyCount))
  1449. {
  1450. if (1 == thisKeyCount)
  1451. {
  1452. // Need to allow defaulted key names
  1453. CComBSTR keyName, otherKeyName;
  1454. CComVariant value, otherValue;
  1455. WbemCimtypeEnum cimType, otherCimType;
  1456. if (GetKey (0, keyName, value, cimType) &&
  1457. otherPath.GetKey (0, otherKeyName, otherValue, otherCimType))
  1458. {
  1459. if ((0 == keyName.Length ()) || (0 == otherKeyName.Length ()) ||
  1460. (0 == _wcsicmp (keyName, otherKeyName)))
  1461. result = KeyMatch (value, otherValue);
  1462. }
  1463. }
  1464. else
  1465. {
  1466. // Both non-singleton instances - have to check
  1467. // key values are the same in some order
  1468. bool ok = true;
  1469. for (DWORD i = 0; ok && (i < thisKeyCount); i++)
  1470. {
  1471. CComBSTR keyName;
  1472. CComVariant value;
  1473. WbemCimtypeEnum cimType;
  1474. if (GetKey (i, keyName, value, cimType) && (0 < keyName.Length ()))
  1475. {
  1476. // Look for a matching key (case-insensitive)
  1477. CComBSTR otherKeyName;
  1478. CComVariant otherValue;
  1479. WbemCimtypeEnum otherCimType;
  1480. for (DWORD j = 0; ok && (j < thisKeyCount); j++)
  1481. {
  1482. if (otherPath.GetKey (j, otherKeyName, otherValue, otherCimType)
  1483. && (0 < otherKeyName.Length ()))
  1484. {
  1485. if ((0 == _wcsicmp(keyName, otherKeyName)) && KeyMatch (value, otherValue))
  1486. break;
  1487. }
  1488. else
  1489. ok = false;
  1490. }
  1491. if (ok && (j < thisKeyCount))
  1492. {
  1493. // Got a match
  1494. continue;
  1495. }
  1496. else
  1497. ok = false;
  1498. }
  1499. else
  1500. ok = false;
  1501. }
  1502. if (ok)
  1503. result = true; // all keys have matched
  1504. }
  1505. }
  1506. }
  1507. }
  1508. }
  1509. }
  1510. }
  1511. break;
  1512. }
  1513. }
  1514. return result;
  1515. }