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.

1095 lines
26 KiB

  1. /*++
  2. Copyright (C) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. GENERAL.CPP
  5. Abstract:
  6. Containes some general purpose classes
  7. which are of use to serveral providers.
  8. Specifically, this contains the code for
  9. the classes used to cache open handles and
  10. the classes used to parse the mapping strings.
  11. History:
  12. a-davj 11-Nov-95 Created.
  13. --*/
  14. #include "precomp.h"
  15. #include <tchar.h>
  16. //***************************************************************************
  17. //
  18. // CEntry::CEntry()
  19. //
  20. // DESCRIPTION:
  21. //
  22. // Constructor.
  23. //
  24. //***************************************************************************
  25. CEntry::CEntry()
  26. {
  27. hHandle = NULL;
  28. sPath.Empty();
  29. }
  30. //***************************************************************************
  31. //
  32. // CEntry::~CEntry()
  33. //
  34. // DESCRIPTION:
  35. //
  36. // Destructor.
  37. //
  38. //***************************************************************************
  39. CEntry::~CEntry()
  40. {
  41. sPath.Empty();
  42. }
  43. //***************************************************************************
  44. //
  45. // CHandleCache::~CHandleCache
  46. //
  47. // DESCRIPTION:
  48. //
  49. // Destructor.
  50. //
  51. //***************************************************************************
  52. CHandleCache::~CHandleCache()
  53. {
  54. Delete(0);
  55. }
  56. //***************************************************************************
  57. //
  58. // CHandleCache::lAddToList
  59. //
  60. // DESCRIPTION:
  61. //
  62. // Adds an entry to the handle list.
  63. //
  64. //
  65. // PARAMETERS:
  66. //
  67. // pAdd Name that will be used to retrieve the handle
  68. // hAdd handle to be added
  69. //
  70. // RETURN VALUE:
  71. //
  72. // S_OK all is well.
  73. // WBEM_E_OUT_OF_MEMORY out of memory
  74. //
  75. //***************************************************************************
  76. long int CHandleCache::lAddToList(
  77. IN const TCHAR * pAdd,
  78. IN HANDLE hAdd)
  79. {
  80. CEntry * pNew = new CEntry();
  81. if(pNew == NULL)
  82. return WBEM_E_OUT_OF_MEMORY;
  83. pNew->hHandle = hAdd;
  84. pNew->sPath = pAdd;
  85. if(CFlexArray::no_error != List.Add(pNew))
  86. return WBEM_E_OUT_OF_MEMORY;
  87. return S_OK;
  88. }
  89. //***************************************************************************
  90. //
  91. // CHandleCache::lGetNumMatch
  92. //
  93. // DESCRIPTION:
  94. //
  95. // Returns the number of entries which match the path tokens. For example,
  96. // the path might be HKEY_LOCAL_MACHINE, hardware, description, xyz, and
  97. // if the tokens, were, HKEY_LOCAL_MACHINE, hardware, devicemap, xyz then a
  98. // two would be returned since the first two parts matched.
  99. //
  100. // PARAMETERS:
  101. //
  102. // iEntry Entry to start checking at
  103. // iToken Token to start checking
  104. // Path This object supplies the tokens to be checked.
  105. //
  106. // RETURN VALUE:
  107. //
  108. // see description.
  109. //
  110. //***************************************************************************
  111. long int CHandleCache::lGetNumMatch(
  112. IN int iEntry,
  113. IN int iToken,
  114. IN CProvObj & Path)
  115. {
  116. int iMatch = 0;
  117. for(;iEntry < List.Size() && iToken < Path.iGetNumTokens();
  118. iEntry++, iToken++, iMatch++)
  119. {
  120. CEntry * pCurr = (CEntry *)List.GetAt(iEntry);
  121. TString sTemp = Path.sGetFullToken(iToken);
  122. if(lstrcmpi(pCurr->sPath,sTemp))
  123. break;
  124. }
  125. return iMatch;
  126. }
  127. //***************************************************************************
  128. //
  129. // CHandleCache::Delete
  130. //
  131. // DESCRIPTION:
  132. //
  133. // Empties all or part of the cache.
  134. //
  135. // PARAMETERS:
  136. //
  137. // lStart Indicates first element to delete. To empty entire cache,
  138. // a zero should be entered.
  139. //
  140. //***************************************************************************
  141. void CHandleCache::Delete(
  142. IN long int lStart)
  143. {
  144. int iCurr;
  145. for(iCurr = List.Size()-1; iCurr >= lStart; iCurr--)
  146. {
  147. CEntry * pCurr = (CEntry *)List.GetAt(iCurr);
  148. delete pCurr;
  149. List.RemoveAt(iCurr);
  150. }
  151. }
  152. //***************************************************************************
  153. //
  154. // CHandleCache::hGetHandle
  155. //
  156. // DESCRIPTION:
  157. //
  158. // Gets a handle.
  159. //
  160. // PARAMETERS:
  161. //
  162. // lIndex Indicates which handle to get. 0 is the first.
  163. //
  164. // RETURN VALUE:
  165. // handle retuested, NULL only if bad index is entered.
  166. //
  167. //***************************************************************************
  168. HANDLE CHandleCache::hGetHandle(
  169. IN long int lIndex)
  170. {
  171. if(lIndex < List.Size())
  172. {
  173. CEntry * pCurr = (CEntry *)List.GetAt(lIndex);
  174. if(pCurr)
  175. return pCurr->hHandle;
  176. }
  177. return NULL;
  178. }
  179. //***************************************************************************
  180. //
  181. // CHandleCache::sGetString
  182. //
  183. // DESCRIPTION:
  184. //
  185. // Gets the string associated with a cache entry.
  186. //
  187. // PARAMETERS:
  188. //
  189. // lIndex Index in cache, 0 is the first element.
  190. //
  191. // RETURN VALUE:
  192. //
  193. // Returns a pointer to the string. NULL if bad index.
  194. //
  195. //***************************************************************************
  196. const TCHAR * CHandleCache::sGetString(
  197. IN long int lIndex)
  198. {
  199. if(lIndex < List.Size()) {
  200. CEntry * pCurr = (CEntry *)List.GetAt(lIndex);
  201. if(pCurr)
  202. return pCurr->sPath;
  203. }
  204. return NULL;
  205. }
  206. //***************************************************************************
  207. //
  208. // CToken::CToken
  209. //
  210. // DESCRIPTION:
  211. //
  212. // constructor.
  213. //
  214. // PARAMETERS:
  215. //
  216. // cpStart String to be parsed.
  217. // cDelim Token delimeter.
  218. // bUsesEscapes If true, then need to look for special characters
  219. //
  220. //***************************************************************************
  221. #define MAX_TEMP 150
  222. CToken::CToken(
  223. IN const TCHAR * cpStart,
  224. IN const OLECHAR cDelim,
  225. bool bUsesEscapes)
  226. {
  227. const TCHAR * cpCurr; //atoi
  228. iOriginalLength = -1;
  229. TString *psExp;
  230. int iNumQuote;
  231. BOOL bLastWasEsc, bInExp, bInString;
  232. bLastWasEsc = bInExp = bInString = FALSE;
  233. // Before doing an elaborate parse, first check for the simple case where there
  234. // are no quotes, escapes, commas, etc
  235. bool bGotSpecialChar = false;
  236. for(cpCurr = cpStart; *cpCurr && *cpCurr != cDelim; cpCurr++)
  237. {
  238. if(*cpCurr == ESC || *cpCurr == '\"' || *cpCurr == '(')
  239. bGotSpecialChar = true;
  240. }
  241. if(!bUsesEscapes || cDelim != MAIN_DELIM || *cpCurr == cDelim || !bGotSpecialChar)
  242. {
  243. // Simple case do it quickly
  244. iOriginalLength = cpCurr - cpStart;
  245. if(iOriginalLength < MAX_TEMP)
  246. {
  247. TCHAR tcTemp[MAX_TEMP];
  248. lstrcpyn(tcTemp, cpStart, iOriginalLength + 1);
  249. sFullData = tcTemp;
  250. sData = tcTemp;
  251. if(*cpCurr)
  252. iOriginalLength++;
  253. return;
  254. }
  255. }
  256. for(cpCurr = cpStart; *cpCurr; cpCurr++) {
  257. // check if end of token
  258. if(*cpCurr == cDelim && !bLastWasEsc) {
  259. cpCurr++;
  260. break;
  261. }
  262. // full data stores everything. Check if character
  263. // is the escape which means that the following
  264. // character should be interpreted as a literal
  265. sFullData += *cpCurr;
  266. if(*cpCurr == ESC && !bLastWasEsc) {
  267. bLastWasEsc = TRUE;
  268. continue;
  269. }
  270. // tokens can include indexs of the form
  271. // (xxx) or ("xxx"). If an index is detected,
  272. // then store the characters between () separately
  273. if((*cpCurr == '(' && !bInExp && !bLastWasEsc)||
  274. (*cpCurr == ',' && bInExp && !bLastWasEsc)) {
  275. // start of index expression. Allocate a new
  276. // string to store it and store the string
  277. // in the expression collection.
  278. psExp = new (TString);
  279. if(psExp) {
  280. Expressions.Add((CObject *)psExp);
  281. bInExp = TRUE;
  282. iNumQuote = 0;
  283. }
  284. }
  285. else if(*cpCurr == ')' && bInExp && !bInString && !bLastWasEsc)
  286. bInExp = FALSE; // end of index expression
  287. else if (*cpCurr == '\"' && bInExp && !bLastWasEsc) {
  288. iNumQuote++;
  289. if(iNumQuote == 1) {
  290. bInString = TRUE;
  291. *psExp += *cpCurr;
  292. }
  293. else if(iNumQuote == 2)
  294. bInString = FALSE;
  295. else
  296. return;
  297. }
  298. else if (bInExp)
  299. *psExp += *cpCurr;
  300. else
  301. sData += *cpCurr;
  302. bLastWasEsc = FALSE;
  303. }
  304. if(bInString || bInExp)
  305. return; // got junk!!!
  306. iOriginalLength = cpCurr - cpStart;
  307. return;
  308. }
  309. //***************************************************************************
  310. //
  311. // CToken::~CToken
  312. //
  313. // DESCRIPTION:
  314. //
  315. // Destructor.
  316. //
  317. //***************************************************************************
  318. CToken::~CToken()
  319. {
  320. int iCnt;
  321. TString * pCurr;
  322. for (iCnt = 0; iCnt < Expressions.Size(); iCnt++) {
  323. pCurr = (TString *)Expressions.GetAt(iCnt);
  324. delete pCurr;
  325. }
  326. Expressions.Empty();
  327. sData.Empty();
  328. sFullData.Empty();
  329. }
  330. //***************************************************************************
  331. //
  332. // CToken::iConvOprand
  333. //
  334. // DESCRIPTION:
  335. //
  336. // Converts the characters in a string into an integer.
  337. //
  338. // PARAMETERS:
  339. //
  340. // tpCurr String to be converted.
  341. // iArray Not used anymore.
  342. // dwValue where the result is set.
  343. //
  344. // RETURN VALUE:
  345. //
  346. // Number of digits converted.
  347. //
  348. //***************************************************************************
  349. long int CToken::iConvOprand(
  350. IN const TCHAR * tpCurr,
  351. IN int iArray,
  352. OUT long int & dwValue)
  353. {
  354. TString sTemp;
  355. long int iRet = 0;
  356. // Build up a string containing
  357. // all characters upto the first non didgit
  358. for(;*tpCurr; tpCurr++)
  359. if(iswdigit(*tpCurr))
  360. {
  361. sTemp += *tpCurr;
  362. iRet++;
  363. }
  364. else
  365. break;
  366. // Convert and return the length
  367. dwValue = _ttoi(sTemp);
  368. return iRet;
  369. }
  370. //***************************************************************************
  371. //
  372. // CToken::GetIntExp
  373. //
  374. // DESCRIPTION:
  375. //
  376. // Converts the expression into an integer. The expression
  377. // can only be made up of integers, '+', '-' and a special
  378. // character ('#' as of now)for substituting iArray. Examples,
  379. // (23) (#+3) (#-4)
  380. //
  381. // PARAMETERS:
  382. //
  383. // iExp which integer to retrieve in the case where you have 2,5,8
  384. // iArray Not used anymore
  385. //
  386. // RETURN VALUE:
  387. //
  388. // -1 if error.
  389. //
  390. //***************************************************************************
  391. long int CToken::GetIntExp(int iExp,int iArray)
  392. {
  393. TString * psTest;
  394. TString sNoBlanks;
  395. TCHAR const * tpCurr;
  396. long int lOpSize;
  397. int iCnt;
  398. long int lAccum = 0, lOperand;
  399. TCHAR tUnary = ' ';
  400. TCHAR tBinary = '+';
  401. BOOL bNeedOperator = FALSE; // Start off needing operand
  402. // Do some intial check such as making sure the expression
  403. // exists and that it isnt a string expression
  404. if(Expressions.Size() <= iExp)
  405. return -1;
  406. if(IsExpString(iExp))
  407. return -1;
  408. psTest = (TString *)Expressions.GetAt(iExp);
  409. if(psTest == NULL) {
  410. return -1;
  411. }
  412. // Get rid of any blanks
  413. for(iCnt = 0; iCnt < psTest->Length(); iCnt++)
  414. if(psTest->GetAt(iCnt) != ' ')
  415. sNoBlanks += psTest->GetAt(iCnt);
  416. // Evalate the expression
  417. for(tpCurr = sNoBlanks; *tpCurr; tpCurr++)
  418. {
  419. if(*tpCurr == '+' || *tpCurr == '-')
  420. {
  421. // got an operator. Note that if an operator is not needed,
  422. // such as before the first operand, then it must be a unary
  423. // operator. Only one unary operator in a row is valid.
  424. if(bNeedOperator)
  425. {
  426. tBinary = *tpCurr;
  427. bNeedOperator = FALSE;
  428. }
  429. else
  430. {
  431. if(tUnary != ' ') // Gratuitous unary operator
  432. return -1;
  433. tUnary = *tpCurr;
  434. }
  435. }
  436. else
  437. {
  438. // got an operand
  439. if(bNeedOperator) // Gratuitous unary operand
  440. return -1;
  441. lOpSize = iConvOprand(tpCurr,iArray,lOperand);
  442. if(lOpSize > 1)
  443. tpCurr += lOpSize-1;
  444. if(tUnary == '-')
  445. lOperand = -lOperand;
  446. if(tBinary == '+')
  447. lAccum = lAccum + lOperand;
  448. else
  449. lAccum = lAccum - lOperand;
  450. bNeedOperator = TRUE;
  451. tUnary = ' ';
  452. }
  453. }
  454. return lAccum;
  455. }
  456. //***************************************************************************
  457. //
  458. // CToken::GetStringExp
  459. //
  460. // DESCRIPTION:
  461. //
  462. // Returns a string expression.
  463. //
  464. // PARAMETERS:
  465. //
  466. // iExp Which string to use when they are separated by commans
  467. //
  468. // RETURN VALUE:
  469. //
  470. // Pointer to string, NULL if iExp is bogus.
  471. //
  472. //***************************************************************************
  473. TCHAR const * CToken::GetStringExp(
  474. IN int iExp)
  475. {
  476. TString * psTest;
  477. TCHAR const * tp;
  478. // start by making sure expression exists.
  479. if(Expressions.Size() <= iExp)
  480. return NULL;
  481. psTest = (TString *)Expressions.GetAt(iExp);
  482. if(psTest != NULL)
  483. {
  484. int iIndex;
  485. iIndex = psTest->Find('\"');
  486. if(iIndex != -1)
  487. {
  488. // All is well. Return a pointer one passed
  489. // the initial \" whose only purpose is to
  490. // indicate that this is a string expression.
  491. tp = *psTest;
  492. return tp + iIndex + 1;
  493. }
  494. }
  495. return NULL;
  496. }
  497. //***************************************************************************
  498. //
  499. // CToken::IsExpString
  500. //
  501. // DESCRIPTION:
  502. //
  503. // Tests if the token contains a string
  504. //
  505. // PARAMETERS:
  506. //
  507. // iExp Indicates which substring for when the strings are divided
  508. // by commas
  509. //
  510. // RETURN VALUE:
  511. // Returns true if the expression is a string.
  512. //
  513. //***************************************************************************
  514. BOOL CToken::IsExpString(int iExp)
  515. {
  516. TString * psTest;
  517. // make sure that the expression exists.
  518. if(Expressions.Size() <= iExp)
  519. return FALSE;
  520. psTest = (TString *)Expressions.GetAt(iExp);
  521. if(psTest != NULL) {
  522. int iIndex;
  523. // String expressions always contain at least one \"
  524. iIndex = psTest->Find('\"');
  525. if(iIndex != -1)
  526. return TRUE;
  527. }
  528. return FALSE;
  529. }
  530. //***************************************************************************
  531. //
  532. // CProvObj::CProvObj(const char * ProviderString,const TCHAR cDelim)
  533. //
  534. // DESCRIPTION:
  535. //
  536. // Constructor.
  537. //
  538. // PARAMETERS:
  539. //
  540. // ProviderString String passed from wbem
  541. // cDelim Token delimeter
  542. // bUsesEscapes True if we need to treat escapes in a special way.
  543. //
  544. //***************************************************************************
  545. #ifndef UNICODE
  546. CProvObj::CProvObj(
  547. IN const char * ProviderString,
  548. IN const TCHAR cDelim, bool bUsesEscapes)
  549. {
  550. m_bUsesEscapes = bUsesEscapes;
  551. Init(ProviderString,cDelim);
  552. return;
  553. }
  554. #endif
  555. //***************************************************************************
  556. //
  557. // CProvObj::CProvObj(const WCHAR * ProviderString,const TCHAR cDelim)
  558. //
  559. // DESCRIPTION:
  560. //
  561. // Constructor.
  562. //
  563. // PARAMETERS:
  564. //
  565. // ProviderString String passed from wbem
  566. // cDelim Token delimeter
  567. //
  568. //***************************************************************************
  569. CProvObj::CProvObj(
  570. IN const WCHAR * ProviderString,
  571. IN const TCHAR cDelim, bool bUsesEscapes)
  572. {
  573. m_bUsesEscapes = bUsesEscapes;
  574. #ifdef UNICODE
  575. Init(ProviderString,cDelim);
  576. #else
  577. char * pTemp = WideToNarrowA(ProviderString);
  578. if(pTemp == NULL)
  579. dwStatus = WBEM_E_FAILED;
  580. else {
  581. Init(pTemp,cDelim);
  582. delete pTemp;
  583. }
  584. #endif
  585. return;
  586. }
  587. //***************************************************************************
  588. //
  589. // void CProvObj::Init
  590. //
  591. // DESCRIPTION:
  592. //
  593. // Doest the acutal work for the various constructors.
  594. //
  595. // PARAMETERS:
  596. // ProviderString String passed from wbem
  597. // cDelim Token delimeter
  598. //
  599. //***************************************************************************
  600. void CProvObj::Init(
  601. IN const TCHAR * ProviderString,
  602. IN const TCHAR cDelim)
  603. {
  604. CToken * pNewToken;
  605. const TCHAR * cpCurr;
  606. m_cDelim = cDelim;
  607. // Create a list of tokens
  608. for(cpCurr = ProviderString; *cpCurr;cpCurr+=pNewToken->GetOrigLength())
  609. {
  610. int iRet = 0;
  611. pNewToken = new CToken(cpCurr,cDelim, m_bUsesEscapes);
  612. if(pNewToken)
  613. iRet = myTokens.Add(pNewToken);
  614. if(pNewToken == NULL || iRet != CFlexArray::no_error)
  615. {
  616. dwStatus = WBEM_E_OUT_OF_MEMORY;
  617. return;
  618. }
  619. if(pNewToken->GetOrigLength() == -1)
  620. {
  621. dwStatus = WBEM_E_INVALID_PARAMETER;
  622. return;
  623. }
  624. }
  625. dwStatus = WBEM_NO_ERROR;
  626. return;
  627. }
  628. //***************************************************************************
  629. //
  630. // CProvObj::Empty
  631. //
  632. // DESCRIPTION:
  633. //
  634. // frees up all the data
  635. //
  636. //***************************************************************************
  637. void CProvObj::Empty(void)
  638. {
  639. int iCnt;
  640. CToken * pCurr;
  641. for (iCnt = 0; iCnt < myTokens.Size(); iCnt++) {
  642. pCurr = (CToken *)myTokens.GetAt(iCnt);
  643. delete pCurr;
  644. }
  645. myTokens.Empty();
  646. }
  647. //***************************************************************************
  648. //
  649. // BOOL CProvObj::Update
  650. //
  651. // DESCRIPTION:
  652. //
  653. // Resets the value with a new provider string.
  654. //
  655. // PARAMETERS:
  656. //
  657. // pwcProvider New provider string
  658. //
  659. // RETURN VALUE:
  660. //
  661. // TRUE if ok.
  662. //***************************************************************************
  663. BOOL CProvObj::Update(
  664. IN WCHAR * pwcProvider)
  665. {
  666. // Do a quick check to see if the "fast" update can be used
  667. BOOL bComplex = FALSE;
  668. int iDelim = 0;
  669. WCHAR * pwcCurr;
  670. for(pwcCurr = pwcProvider; *pwcCurr; pwcCurr++)
  671. {
  672. if(*pwcCurr == m_cDelim)
  673. iDelim++;
  674. else if(*pwcCurr == ESC || *pwcCurr == L'\"' || *pwcCurr == L'(')
  675. {
  676. bComplex = TRUE;
  677. break;
  678. }
  679. }
  680. // If the number of tokens changed, or there is some embedded junk
  681. // just empty and retry.
  682. if(bComplex || iDelim != myTokens.Size()-1)
  683. {
  684. Empty();
  685. #ifdef UNICODE
  686. Init(pwcProvider,m_cDelim);
  687. #else
  688. char * pTemp = WideToNarrowA(pwcProvider);
  689. if(pTemp == NULL)
  690. return FALSE;
  691. Init(pTemp,m_cDelim);
  692. delete pTemp;
  693. #endif
  694. return TRUE;
  695. }
  696. // We can take the shortcut. Start by creating a TCHAR temp version
  697. int iLen = 2*wcslen(pwcProvider) + 1;
  698. TCHAR * pTemp = new TCHAR[iLen];
  699. if(pTemp == NULL)
  700. return FALSE;
  701. #ifdef UNICODE
  702. wcscpy(pTemp,pwcProvider);
  703. #else
  704. wcstombs(pTemp, pwcProvider, iLen);
  705. #endif
  706. TCHAR * ptcCurr;
  707. TCHAR * pStart;
  708. BOOL bTheEnd = FALSE;
  709. iDelim = 0;
  710. for(pStart = ptcCurr = pTemp;!bTheEnd;ptcCurr++)
  711. {
  712. if(*ptcCurr == m_cDelim || *ptcCurr == NULL)
  713. {
  714. bTheEnd = (*ptcCurr == NULL);
  715. *ptcCurr = NULL;
  716. CToken * pToken = (CToken *)myTokens.GetAt(iDelim);
  717. if(pToken && lstrcmpi(pStart,pToken->sFullData))
  718. {
  719. pToken->sFullData = pStart;
  720. pToken->sData = pStart;
  721. }
  722. iDelim++;
  723. pStart = ptcCurr+1;
  724. }
  725. }
  726. delete pTemp;
  727. return TRUE;
  728. }
  729. //***************************************************************************
  730. //
  731. // CProvObj::GetTokenPointer
  732. //
  733. // DESCRIPTION:
  734. //
  735. // Gets a pointer to a token
  736. //
  737. // PARAMETERS:
  738. //
  739. // iToken Which token to get
  740. //
  741. // RETURN VALUE:
  742. //
  743. // pointer to token, or NULL if bad request.
  744. //
  745. //***************************************************************************
  746. CToken * CProvObj::GetTokenPointer(
  747. IN int iToken)
  748. {
  749. if(iToken >= myTokens.Size() || iToken < 0)
  750. return NULL;
  751. return (CToken *)myTokens.GetAt(iToken);
  752. }
  753. //***************************************************************************
  754. //
  755. // CProvObj::dwGetStatus
  756. //
  757. // DESCRIPTION:
  758. //
  759. // Gets status and also checks to make sure a minimum number of tokens
  760. // exist.
  761. //
  762. // PARAMETERS:
  763. //
  764. // iMin minimum number of tokens.
  765. //
  766. // RETURN VALUE:
  767. //
  768. // Returns S_OK if OK, WBEM_E_FAILED otherwise.
  769. //
  770. //***************************************************************************
  771. DWORD CProvObj::dwGetStatus(
  772. IN int iMin)
  773. {
  774. if(dwStatus)
  775. return dwStatus;
  776. else
  777. return (iMin <= myTokens.Size()) ? S_OK : WBEM_E_FAILED;
  778. }
  779. //***************************************************************************
  780. //
  781. // CProvObj::sGetToken
  782. //
  783. // DESCRIPTION:
  784. //
  785. // Gets a token. Note that the token will not include embleded "(stuff)"
  786. //
  787. // PARAMETERS:
  788. //
  789. // iToken which token to get
  790. //
  791. // RETURN VALUE:
  792. //
  793. // pointer to token, NULL if invalid argument
  794. //***************************************************************************
  795. const TCHAR * CProvObj::sGetToken(
  796. IN int iToken)
  797. {
  798. CToken * pCurr = GetTokenPointer(iToken);
  799. return (pCurr) ? pCurr->GetStringValue() : NULL;
  800. }
  801. //***************************************************************************
  802. //
  803. // const TCHAR * CProvObj::sGetFullToken
  804. //
  805. // DESCRIPTION:
  806. //
  807. // Gets a full and unadulterated token.
  808. //
  809. // PARAMETERS:
  810. //
  811. // iToken token to get
  812. //
  813. // RETURN VALUE:
  814. //
  815. // pointer to token, NULL if invalid argument
  816. //***************************************************************************
  817. const TCHAR * CProvObj::sGetFullToken(
  818. IN int iToken)
  819. {
  820. CToken * pCurr = GetTokenPointer(iToken);
  821. return (pCurr) ? pCurr->GetFullStringValue() : NULL;
  822. }
  823. //***************************************************************************
  824. //
  825. // const TCHAR * CProvObj::sGetStringExp
  826. //
  827. // DESCRIPTION:
  828. //
  829. // Gets a substring for a particular token
  830. //
  831. // PARAMETERS:
  832. //
  833. // iToken token to get
  834. // iExp substring to get
  835. //
  836. // RETURN VALUE:
  837. //
  838. // pointer to substring, NULL if invalid argument
  839. //***************************************************************************
  840. const TCHAR * CProvObj::sGetStringExp(
  841. IN int iToken,
  842. IN int iExp)
  843. {
  844. CToken * pCurr = GetTokenPointer(iToken);
  845. return (pCurr) ? pCurr->GetStringExp(iExp) : NULL;
  846. }
  847. //***************************************************************************
  848. //
  849. // long int CProvObj::iGetIntExp
  850. //
  851. // DESCRIPTION:
  852. //
  853. // For a particular token, gets the integer value of a substring.
  854. //
  855. // PARAMETERS:
  856. //
  857. // iToken token to get
  858. // iExp substring
  859. // iArray no longer used
  860. //
  861. // RETURN VALUE:
  862. //
  863. // int value, or -1 if bad argument
  864. //***************************************************************************
  865. long int CProvObj::iGetIntExp(
  866. IN int iToken,
  867. IN int iExp,
  868. IN int iArray)
  869. {
  870. CToken * pCurr = GetTokenPointer(iToken);
  871. return (pCurr) ? pCurr->GetIntExp(iExp,iArray) : -1;
  872. }
  873. //***************************************************************************
  874. //
  875. // BOOL CProvObj::IsExpString
  876. //
  877. // DESCRIPTION:
  878. //
  879. // Tests a substring to see if it is a string, or numeric
  880. //
  881. // PARAMETERS:
  882. //
  883. // iToken token to get
  884. // iExp substring
  885. //
  886. //
  887. // RETURN VALUE:
  888. //
  889. // True if arguments are valid and it is not numeric
  890. //***************************************************************************
  891. BOOL CProvObj::IsExpString(
  892. IN int iToken,
  893. IN int iExp)
  894. {
  895. CToken * pCurr = GetTokenPointer(iToken);
  896. return (pCurr) ? pCurr->IsExpString(iExp) : FALSE;
  897. }
  898. //***************************************************************************
  899. //
  900. // long int CProvObj::iGetNumExp
  901. //
  902. // DESCRIPTION:
  903. //
  904. // Gets the number of subexpressions
  905. //
  906. // PARAMETERS:
  907. //
  908. // iToken token to check
  909. //
  910. // RETURN VALUE:
  911. //
  912. // number of substrings (subexpressions) or -1 if invalid argument
  913. //***************************************************************************
  914. long int CProvObj::iGetNumExp(
  915. IN int iToken)
  916. {
  917. CToken * pCurr = GetTokenPointer(iToken);
  918. return (pCurr) ? pCurr->GetNumExp() : -1;
  919. }
  920. //***************************************************************************
  921. //
  922. // IWbemClassObject * GetNotifyObj
  923. //
  924. // DESCRIPTION:
  925. //
  926. // This utility is useful for setting notify objects
  927. // at the end of async calls.
  928. //
  929. // PARAMETERS:
  930. //
  931. // pServices pointer back into WBEM
  932. // lRet status code to set in notify object
  933. //
  934. // RETURN VALUE:
  935. //
  936. // Class object. Null if failure.
  937. //***************************************************************************
  938. IWbemClassObject * GetNotifyObj(
  939. IN IWbemServices * pServices,
  940. IN long lRet,
  941. IN IWbemContext *pCtx)
  942. {
  943. if(pServices == NULL)
  944. return NULL;
  945. IWbemClassObject * pInst = NULL;
  946. IWbemClassObject * pClass = NULL;
  947. SCODE sc = pServices->GetObject(L"__ExtendedStatus", 0, pCtx, &pClass, NULL);
  948. if(sc != S_OK)
  949. return NULL;
  950. sc = pClass->SpawnInstance(0, &pInst);
  951. pClass->Release();
  952. if(sc == S_OK && pInst)
  953. {
  954. VARIANT v;
  955. v.vt = VT_I4;
  956. v.lVal = lRet;
  957. sc = pInst->Put(L"StatusCode", 0, &v, 0);
  958. if(sc != S_OK)
  959. {
  960. pInst->Release();
  961. return NULL;
  962. }
  963. else
  964. return pInst;
  965. }
  966. return NULL;
  967. }