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.

870 lines
14 KiB

  1. //***************************************************************************
  2. //
  3. // Useful.CPP
  4. //
  5. // Module: CDM Provider
  6. //
  7. // Purpose: Useful classes
  8. //
  9. // Copyright (c) 2000 Microsoft Corporation
  10. //
  11. //***************************************************************************
  12. #include <objbase.h>
  13. #include <wbemprov.h>
  14. #include "debug.h"
  15. #include "useful.h"
  16. #include "wbemmisc.h"
  17. void FreeTheBSTRArray(
  18. BSTR *Array,
  19. ULONG Size
  20. )
  21. /*+++
  22. Routine Description:
  23. This routine will free the contents of an array of BSTR and then
  24. the array itself
  25. Arguments:
  26. Array is the array to be freed
  27. Size is the number of elements in the array
  28. Return Value:
  29. HRESULT
  30. ---*/
  31. {
  32. ULONG i;
  33. if (Array != NULL)
  34. {
  35. for (i = 0; i < Size; i++)
  36. {
  37. if (Array[i] != NULL)
  38. {
  39. SysFreeString(Array[i]);
  40. }
  41. }
  42. WmipFree(Array);
  43. }
  44. }
  45. CBstrArray::CBstrArray()
  46. {
  47. Array = NULL;
  48. ListSize = 0xffffffff;
  49. }
  50. CBstrArray::~CBstrArray()
  51. {
  52. ULONG i;
  53. if (Array != NULL)
  54. {
  55. for (i = 0; i < ListSize; i++)
  56. {
  57. if (Array[i] != NULL)
  58. {
  59. SysFreeString(Array[i]);
  60. }
  61. }
  62. WmipFree(Array);
  63. }
  64. ListSize = 0xffffffff;
  65. }
  66. HRESULT CBstrArray::Initialize(
  67. ULONG ListCount
  68. )
  69. {
  70. HRESULT hr = WBEM_S_NO_ERROR;
  71. ULONG AllocSize;
  72. if (ListCount != 0)
  73. {
  74. AllocSize = ListCount * sizeof(BSTR *);
  75. Array = (BSTR *)WmipAlloc(AllocSize);
  76. if (Array != NULL)
  77. {
  78. memset(Array, 0, AllocSize);
  79. ListSize = ListCount;
  80. } else {
  81. hr = WBEM_E_OUT_OF_MEMORY;
  82. }
  83. } else {
  84. ListSize = ListCount;
  85. }
  86. return(hr);
  87. }
  88. BOOLEAN CBstrArray::IsInitialized(
  89. )
  90. {
  91. return( (Array != NULL) || (ListSize == 0) );
  92. }
  93. BSTR CBstrArray::Get(
  94. ULONG Index
  95. )
  96. {
  97. WmipAssert(Index < ListSize);
  98. WmipAssert(IsInitialized());
  99. return(Array[Index]);
  100. }
  101. void CBstrArray::Set(
  102. ULONG Index,
  103. BSTR s
  104. )
  105. {
  106. WmipAssert(Index < ListSize);
  107. WmipAssert(IsInitialized());
  108. Array[Index] = s;
  109. }
  110. ULONG CBstrArray::GetListSize(
  111. )
  112. {
  113. WmipAssert(IsInitialized());
  114. return(ListSize);
  115. }
  116. CWbemObjectList::CWbemObjectList()
  117. {
  118. //
  119. // Constructor, init internal values
  120. //
  121. List = NULL;
  122. RelPaths = NULL;
  123. ListSize = 0xffffffff;
  124. }
  125. CWbemObjectList::~CWbemObjectList()
  126. {
  127. ULONG i;
  128. //
  129. // Destructor, free memory held by this class
  130. //
  131. if (List != NULL)
  132. {
  133. for (i = 0; i < ListSize; i++)
  134. {
  135. if (List[i] != NULL)
  136. {
  137. List[i]->Release();
  138. }
  139. }
  140. WmipFree(List);
  141. }
  142. List = NULL;
  143. if (RelPaths != NULL)
  144. {
  145. FreeTheBSTRArray(RelPaths, ListSize);
  146. RelPaths = NULL;
  147. }
  148. ListSize = 0xffffffff;
  149. }
  150. HRESULT CWbemObjectList::Initialize(
  151. ULONG NumberPointers
  152. )
  153. {
  154. HRESULT hr;
  155. ULONG AllocSize;
  156. //
  157. // Initialize class by allocating internal list array
  158. //
  159. WmipAssert(List == NULL);
  160. if (NumberPointers != 0)
  161. {
  162. AllocSize = NumberPointers * sizeof(IWbemClassObject *);
  163. List = (IWbemClassObject **)WmipAlloc(AllocSize);
  164. if (List != NULL)
  165. {
  166. memset(List, 0, AllocSize);
  167. AllocSize = NumberPointers * sizeof(BSTR);
  168. RelPaths = (BSTR *)WmipAlloc(AllocSize);
  169. if (RelPaths != NULL)
  170. {
  171. memset(RelPaths, 0, AllocSize);
  172. ListSize = NumberPointers;
  173. hr = WBEM_S_NO_ERROR;
  174. } else {
  175. WmipDebugPrint(("CDMProv: Could not alloc memory for CWbemObjectList RelPaths\n"));
  176. hr = WBEM_E_OUT_OF_MEMORY;
  177. }
  178. } else {
  179. WmipDebugPrint(("CDMProv: Could not alloc memory for CWbemObjectList\n"));
  180. hr = WBEM_E_OUT_OF_MEMORY;
  181. }
  182. } else {
  183. ListSize = NumberPointers;
  184. hr = WBEM_S_NO_ERROR;
  185. }
  186. return(hr);
  187. }
  188. ULONG CWbemObjectList::GetListSize(
  189. void
  190. )
  191. {
  192. //
  193. // Accessor for list size
  194. //
  195. WmipAssert(IsInitialized());
  196. return(ListSize);
  197. }
  198. IWbemClassObject *CWbemObjectList::Get(
  199. ULONG Index
  200. )
  201. { IWbemClassObject *Pointer;
  202. WmipAssert(Index < ListSize);
  203. WmipAssert(IsInitialized());
  204. Pointer = List[Index];
  205. return(Pointer);
  206. }
  207. HRESULT CWbemObjectList::Set(
  208. IN ULONG Index,
  209. IN IWbemClassObject *Pointer
  210. )
  211. {
  212. HRESULT hr;
  213. VARIANT v;
  214. WmipAssert(Pointer != NULL);
  215. WmipAssert(Index < ListSize);
  216. WmipAssert(IsInitialized());
  217. hr = WmiGetProperty(Pointer,
  218. L"__RelPath",
  219. CIM_REFERENCE,
  220. &v);
  221. if (hr == WBEM_S_NO_ERROR)
  222. {
  223. RelPaths[Index] = v.bstrVal;
  224. List[Index] = Pointer;
  225. }
  226. return(hr);
  227. }
  228. BSTR /* NOFREE */ CWbemObjectList::GetRelPath(
  229. IN ULONG Index
  230. )
  231. {
  232. WmipAssert(Index < ListSize);
  233. WmipAssert(IsInitialized());
  234. return(RelPaths[Index]);
  235. }
  236. BOOLEAN CWbemObjectList::IsInitialized(
  237. )
  238. {
  239. return((ListSize == 0) ||
  240. ((List != NULL) && (RelPaths != NULL)));
  241. }
  242. CValueMapping::CValueMapping(
  243. )
  244. {
  245. VariantInit(&Values);
  246. ValueMap = NULL;
  247. }
  248. CValueMapping::~CValueMapping(
  249. )
  250. {
  251. if (ValueMap != NULL)
  252. {
  253. WmipFree(ValueMap);
  254. }
  255. VariantClear(&Values);
  256. }
  257. HRESULT CValueMapping::EstablishByName(
  258. IWbemServices *pServices,
  259. PWCHAR ClassName,
  260. PWCHAR PropertyName
  261. )
  262. {
  263. HRESULT hr;
  264. PWCHAR Names[2];
  265. VARTYPE Types[2];
  266. VARIANT v[2];
  267. VARTYPE IsValueMapArray, IsValuesArray;
  268. Names[0] = L"ValueMap";
  269. Types[0] = VT_BSTR;
  270. Names[1] = L"Values";
  271. Types[1] = VT_BSTR;
  272. hr = WmiGetQualifierListByName(pServices,
  273. ClassName,
  274. PropertyName,
  275. 2,
  276. Names,
  277. Types,
  278. v);
  279. if (hr == WBEM_S_NO_ERROR)
  280. {
  281. IsValueMapArray = v[0].vt & VT_ARRAY;
  282. IsValuesArray = v[1].vt & VT_ARRAY;
  283. if (IsValueMapArray == IsValuesArray)
  284. {
  285. if (IsValueMapArray)
  286. {
  287. //
  288. // Qualifiers specified as arrays so we can just
  289. // set them up
  290. //
  291. hr = EstablishByArrays(&v[1],
  292. &v[0]);
  293. } else {
  294. //
  295. // Qualifiers specified as scalars
  296. //
  297. hr = EstablishByScalars(v[1].bstrVal,
  298. v[0].bstrVal);
  299. }
  300. } else {
  301. //
  302. // Both must be an array or a scalar
  303. //
  304. hr = WBEM_E_FAILED;
  305. }
  306. VariantClear(&v[0]);
  307. VariantClear(&v[1]);
  308. }
  309. return(hr);
  310. }
  311. HRESULT CValueMapping::EstablishByScalars(
  312. BSTR vValues,
  313. BSTR vValueMap
  314. )
  315. {
  316. HRESULT hr;
  317. PULONG Number;
  318. LONG Index;
  319. SAFEARRAYBOUND Bound;
  320. //
  321. // First, establish the ValueMap values
  322. //
  323. ValueMap = (PULONG64)WmipAlloc(sizeof(ULONG64));
  324. if (ValueMap != NULL)
  325. {
  326. *ValueMap = _wtoi(vValueMap);
  327. ValueMapElements = 1;
  328. //
  329. // Now build a safearray to store the Values element
  330. //
  331. ValuesLBound = 0;
  332. Bound.lLbound = ValuesLBound;
  333. Bound.cElements = 1;
  334. Values.parray = SafeArrayCreate(VT_BSTR,
  335. 1,
  336. &Bound);
  337. if (Values.parray != NULL)
  338. {
  339. Values.vt = VT_BSTR | VT_ARRAY;
  340. Index = 0;
  341. hr = SafeArrayPutElement(Values.parray,
  342. &Index,
  343. vValues);
  344. if (hr != WBEM_S_NO_ERROR)
  345. {
  346. VariantClear(&Values);
  347. }
  348. }
  349. } else {
  350. hr = WBEM_E_OUT_OF_MEMORY;
  351. }
  352. return(hr);
  353. }
  354. HRESULT CValueMapping::EstablishByArrays(
  355. VARIANT *vValues,
  356. VARIANT *vValueMap
  357. )
  358. {
  359. HRESULT hr;
  360. BSTR s;
  361. LONG ValueMapLBound, ValueMapUBound;
  362. LONG ValuesUBound, ValuesElements;
  363. LONG Index;
  364. LONG i;
  365. //
  366. // Get the array sizes and ensure that they match
  367. //
  368. hr = WmiGetArraySize(vValueMap->parray,
  369. &ValueMapLBound,
  370. &ValueMapUBound,
  371. &ValueMapElements);
  372. if (hr == WBEM_S_NO_ERROR)
  373. {
  374. hr = WmiGetArraySize(vValues->parray,
  375. &ValuesLBound,
  376. &ValuesUBound,
  377. &ValuesElements);
  378. if (hr == WBEM_S_NO_ERROR)
  379. {
  380. if ((ValuesLBound == ValueMapLBound) &&
  381. (ValuesUBound == ValueMapUBound) &&
  382. (ValuesElements == ValueMapElements))
  383. {
  384. //
  385. // The ValueMap is balance with the values so parse the
  386. // valuemaps from strings to ulongs
  387. //
  388. ValueMap = (PULONG64)WmipAlloc(ValueMapElements * sizeof(ULONG64));
  389. if (ValueMap != NULL)
  390. {
  391. for (i = 0; i < ValueMapElements; i++)
  392. {
  393. Index = i + ValueMapLBound;
  394. hr = SafeArrayGetElement(vValueMap->parray,
  395. &Index,
  396. &s);
  397. if (hr == WBEM_S_NO_ERROR)
  398. {
  399. ValueMap[i] = _wtoi(s);
  400. SysFreeString(s);
  401. }
  402. }
  403. //
  404. // And assign Values to our class
  405. //
  406. Values = *vValues;
  407. VariantInit(vValues);
  408. } else {
  409. hr = WBEM_E_OUT_OF_MEMORY;
  410. }
  411. }
  412. }
  413. }
  414. return(hr);
  415. }
  416. HRESULT CValueMapping::MapToString(
  417. IN ULONG64 Number,
  418. OUT BSTR *String
  419. )
  420. {
  421. LONG i;
  422. WCHAR ss[MAX_PATH];
  423. LONG Index;
  424. HRESULT hr;
  425. //
  426. // Loop over all values and try to find a match
  427. //
  428. for (i = 0, hr = WBEM_E_FAILED;
  429. (i < ValueMapElements) && (hr != WBEM_S_NO_ERROR);
  430. i++)
  431. {
  432. if (Number == ValueMap[i])
  433. {
  434. //
  435. // We found something to map the value to
  436. //
  437. Index = i + ValuesLBound;
  438. hr = SafeArrayGetElement(Values.parray,
  439. &Index,
  440. String);
  441. }
  442. }
  443. if (hr != WBEM_S_NO_ERROR)
  444. {
  445. //
  446. // There was no match so we just leave the result as a number
  447. //
  448. wsprintfW(ss, L"%d", Number);
  449. *String = SysAllocString(ss);
  450. if (*String == NULL)
  451. {
  452. hr = WBEM_E_OUT_OF_MEMORY;
  453. }
  454. }
  455. return(hr);
  456. }
  457. HRESULT CValueMapping::MapToNumber(
  458. IN BSTR String,
  459. OUT PULONG64 Number
  460. )
  461. {
  462. LONG i;
  463. BSTR s;
  464. LONG Index;
  465. HRESULT hr, hr2;
  466. for (i = 0, hr = WBEM_E_FAILED;
  467. (i < ValueMapElements) && (hr != WBEM_S_NO_ERROR);
  468. i++)
  469. {
  470. Index = i + ValuesLBound;
  471. hr2 = SafeArrayGetElement(Values.parray,
  472. &Index,
  473. &s);
  474. if (hr2 == WBEM_S_NO_ERROR)
  475. {
  476. if (_wcsicmp(s, String) == 0)
  477. {
  478. *Number = ValueMap[i];
  479. hr = WBEM_S_NO_ERROR;
  480. }
  481. SysFreeString(s);
  482. }
  483. }
  484. //
  485. // There was no match so we don't really have anything to map to
  486. //
  487. return(hr);
  488. }
  489. HRESULT CValueMapping::MapVariantToNumber(
  490. VARIANT *v,
  491. CIMTYPE NewType
  492. )
  493. {
  494. HRESULT hr;
  495. VARTYPE BaseType, IsArray;
  496. ULONG64 Number;
  497. VARTYPE NewVarType;
  498. WCHAR ss[MAX_PATH];
  499. BaseType = v->vt & ~VT_ARRAY;
  500. IsArray = v->vt & VT_ARRAY;
  501. WmipAssert(BaseType == VT_BSTR);
  502. if (IsArray == VT_ARRAY)
  503. {
  504. //
  505. // The variant is an array so we need to map each element in an
  506. // array
  507. //
  508. SAFEARRAYBOUND Bounds;
  509. SAFEARRAY *Array;
  510. ULONG Value;
  511. LONG UBound, LBound, Elements, Index;
  512. BSTR s;
  513. LONG i;
  514. hr = WmiGetArraySize(v->parray,
  515. &LBound,
  516. &UBound,
  517. &Elements);
  518. if (hr == WBEM_S_NO_ERROR)
  519. {
  520. if ((NewType == (CIM_SINT64 | CIM_FLAG_ARRAY)) ||
  521. (NewType == (CIM_UINT64 | CIM_FLAG_ARRAY)))
  522. {
  523. //
  524. // If we are mapping to a 64bit number we need to make
  525. // it into a string so setup as an safearray of strings
  526. //
  527. NewVarType = VT_BSTR | VT_ARRAY;
  528. } else {
  529. NewVarType = (VARTYPE)NewType;
  530. }
  531. Bounds.lLbound = LBound;
  532. Bounds.cElements = Elements;
  533. Array = SafeArrayCreate(NewVarType,
  534. 1,
  535. &Bounds);
  536. if (Array != NULL)
  537. {
  538. for (i = 0;
  539. (i < Elements) && (hr == WBEM_S_NO_ERROR);
  540. i++)
  541. {
  542. Index = i + LBound;
  543. hr = SafeArrayGetElement(v->parray,
  544. &Index,
  545. &s);
  546. if (hr == WBEM_S_NO_ERROR)
  547. {
  548. hr = MapToNumber(s,
  549. &Number);
  550. SysFreeString(s);
  551. if (hr == WBEM_S_NO_ERROR)
  552. {
  553. if (NewVarType == (VT_BSTR | VT_ARRAY))
  554. {
  555. //
  556. // Mapping to a 64bit number so convert
  557. // to string first
  558. //
  559. wsprintfW(ss, L"%d", Number);
  560. s = SysAllocString(ss);
  561. if (s != NULL)
  562. {
  563. hr = SafeArrayPutElement(Array,
  564. &Index,
  565. s);
  566. SysFreeString(s);
  567. } else {
  568. hr = WBEM_E_OUT_OF_MEMORY;
  569. }
  570. } else {
  571. hr = SafeArrayPutElement(Array,
  572. &Index,
  573. &Number);
  574. }
  575. }
  576. }
  577. }
  578. if (hr == WBEM_S_NO_ERROR)
  579. {
  580. VariantClear(v);
  581. v->vt = NewType | VT_ARRAY;
  582. v->parray = Array;
  583. } else {
  584. SafeArrayDestroy(Array);
  585. }
  586. }
  587. }
  588. } else {
  589. //
  590. // The variant is a scalar so we just need to map one thing
  591. //
  592. hr = MapToNumber(v->bstrVal,
  593. &Number);
  594. if (hr == WBEM_S_NO_ERROR)
  595. {
  596. VariantClear(v);
  597. WmiSetNumberInVariant(v,
  598. NewType,
  599. Number);
  600. }
  601. }
  602. return(hr);
  603. }
  604. HRESULT CValueMapping::MapVariantToString(
  605. VARIANT *v,
  606. CIMTYPE OldType
  607. )
  608. {
  609. VARTYPE BaseType, IsArray;
  610. ULONG64 Number;
  611. BSTR s;
  612. HRESULT hr;
  613. LONG i;
  614. BaseType = v->vt & ~VT_ARRAY;
  615. IsArray = v->vt & VT_ARRAY;
  616. if (IsArray == VT_ARRAY)
  617. {
  618. //
  619. // The variant is an array so we need to map each element in an
  620. // array
  621. //
  622. SAFEARRAYBOUND Bounds;
  623. SAFEARRAY *Array;
  624. ULONG Value;
  625. LONG UBound, LBound, Elements, Index;
  626. hr = WmiGetArraySize(v->parray,
  627. &LBound,
  628. &UBound,
  629. &Elements);
  630. if (hr == WBEM_S_NO_ERROR)
  631. {
  632. Bounds.lLbound = LBound;
  633. Bounds.cElements = Elements;
  634. Array = SafeArrayCreate(VT_BSTR,
  635. 1,
  636. &Bounds);
  637. if (Array != NULL)
  638. {
  639. for (i = 0;
  640. (i < Elements) && (hr == WBEM_S_NO_ERROR);
  641. i++)
  642. {
  643. Index = i + LBound;
  644. if (BaseType == VT_BSTR)
  645. {
  646. //
  647. // If base type is a string then we assume that
  648. // we've got a 64bit number which is encoded as
  649. // a string. So we need to fish out the string
  650. // and convert it to a ULONG64
  651. //
  652. WmipAssert((OldType == (CIM_SINT64 | CIM_FLAG_ARRAY)) ||
  653. (OldType == (CIM_UINT64 | CIM_FLAG_ARRAY)));
  654. hr = SafeArrayGetElement(v->parray,
  655. &Index,
  656. &s);
  657. if (hr == WBEM_S_NO_ERROR)
  658. {
  659. Number = _wtoi(s);
  660. SysFreeString(s);
  661. }
  662. } else {
  663. //
  664. // Otherwise the number is acutally encoded as
  665. // a number so fish out the number
  666. //
  667. Number = 0;
  668. hr = SafeArrayGetElement(v->parray,
  669. &Index,
  670. &Number);
  671. }
  672. if (hr == WBEM_S_NO_ERROR)
  673. {
  674. hr = MapToString(Number,
  675. &s);
  676. if (hr == WBEM_S_NO_ERROR)
  677. {
  678. hr = SafeArrayPutElement(Array,
  679. &Index,
  680. s);
  681. SysFreeString(s);
  682. }
  683. }
  684. }
  685. if (hr == WBEM_S_NO_ERROR)
  686. {
  687. VariantClear(v);
  688. v->vt = VT_BSTR | VT_ARRAY;
  689. v->parray = Array;
  690. } else {
  691. SafeArrayDestroy(Array);
  692. }
  693. }
  694. }
  695. } else {
  696. //
  697. // The variant is a scalar so we just need to map one thing
  698. //
  699. WmiGetNumberFromVariant(v,
  700. OldType,
  701. &Number);
  702. hr = MapToString(Number,
  703. &s);
  704. if (hr == WBEM_S_NO_ERROR)
  705. {
  706. VariantClear(v);
  707. v->vt = VT_BSTR;
  708. v->bstrVal = s;
  709. }
  710. }
  711. return(hr);
  712. }
  713. #ifndef HEAP_DEBUG
  714. PVOID WmipAlloc(
  715. IN ULONG Size
  716. )
  717. /*+++
  718. Routine Description:
  719. Internal memory allocator
  720. Arguments:
  721. Size is the number of bytes to allocate
  722. Return Value:
  723. pointer to alloced memory or NULL
  724. ---*/
  725. {
  726. return(LocalAlloc(LPTR, Size));
  727. }
  728. void WmipFree(
  729. IN PVOID Ptr
  730. )
  731. /*+++
  732. Routine Description:
  733. Internal memory deallocator
  734. Arguments:
  735. Pointer to freed memory
  736. Return Value:
  737. void
  738. ---*/
  739. {
  740. WmipAssert(Ptr != NULL);
  741. LocalFree(Ptr);
  742. }
  743. #endif