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.

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