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.

995 lines
22 KiB

  1. /*++
  2. // Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. UmiParse.CPP
  5. Abstract:
  6. Implements the UMI object path parser engine
  7. History:
  8. a-davj 11-feb-00 Created.
  9. --*/
  10. #include "precomp.h"
  11. #include <genlex.h>
  12. #include "umipathlex.h"
  13. #include "PathParse.h"
  14. #include "UMIParse.h"
  15. #include "commain.h"
  16. //#include "resource.h"
  17. #include "wbemcli.h"
  18. #include <stdio.h>
  19. #include <sync.h>
  20. #include "helpers.h"
  21. //***************************************************************************
  22. //
  23. // CUmiPathParser
  24. //
  25. //***************************************************************************
  26. void CUmiPathParser::Zero()
  27. {
  28. m_nCurrentToken = 0;
  29. m_pLexer = 0;
  30. m_pInitialIdent = 0;
  31. m_pOutput = 0;
  32. m_pTmpKeyRef = 0;
  33. }
  34. CUmiPathParser::CUmiPathParser(DWORD eFlags)
  35. : m_eFlags(eFlags)
  36. {
  37. Zero();
  38. }
  39. void CUmiPathParser::Empty()
  40. {
  41. delete m_pLexer;
  42. delete m_pInitialIdent;
  43. delete m_pTmpKeyRef;
  44. // m_pOutput is intentionally left alone,
  45. // since all code paths delete this already on error, or
  46. // else the user acquired the pointer.
  47. }
  48. CUmiPathParser::~CUmiPathParser()
  49. {
  50. Empty();
  51. }
  52. int CUmiPathParser::Parse(
  53. LPCWSTR pRawPath,
  54. CDefPathParser & Output
  55. )
  56. {
  57. bool bRelative = true;
  58. if(m_eFlags != 0)
  59. return CUmiPathParser::InvalidParameter;
  60. if (pRawPath == 0 || wcslen(pRawPath) == 0)
  61. return CUmiPathParser::InvalidParameter;
  62. // Check for leading ws.
  63. // =====================
  64. if (iswspace(pRawPath[0]))
  65. return InvalidParameter;
  66. // These are required for multiple calls to Parse().
  67. // ==================================================
  68. Empty();
  69. Zero();
  70. m_pOutput = &Output;
  71. // Parse the server name (if there is one) manually
  72. // ================================================
  73. if(wcslen(pRawPath) > 6 && towupper(pRawPath[0]) == L'U' && towupper(pRawPath[1]) == L'M' &&
  74. towupper(pRawPath[2]) == L'I' && pRawPath[3] == L':' && pRawPath[4] == L'/' &&
  75. pRawPath[5] == L'/')
  76. {
  77. const WCHAR* pwcStart = pRawPath + 6;
  78. bRelative = false;
  79. // Find the next backslash --- it's the end of the server name
  80. // Since the next slash can be either, search for both and take
  81. // the first one. If the first character is a '[', then then
  82. // end is indicated by a ']'
  83. // ============================================================
  84. WCHAR* pwcEnd = NULL;
  85. if(*pwcStart == L'[')
  86. {
  87. // look for the ']'
  88. WCHAR * pCloseBrace = wcschr(pwcStart, L']');
  89. if(pCloseBrace == NULL)
  90. return SyntaxError;
  91. pwcEnd = pCloseBrace+1;
  92. }
  93. else
  94. {
  95. pwcEnd = wcschr(pwcStart, L'/');;
  96. }
  97. if (pwcEnd == NULL)
  98. {
  99. // If we have already exhausted the object path string,
  100. // a lone server name was all there was.
  101. // ====================================================
  102. return SyntaxError;
  103. }
  104. if(pwcEnd == pwcStart)
  105. {
  106. // No name at all. This is OK in umi
  107. // ==================================
  108. m_pOutput->SetServer(L""); // also sets relative
  109. pRawPath = pwcEnd;
  110. }
  111. else
  112. {
  113. WCHAR * wTemp = new WCHAR[pwcEnd-pwcStart+1];
  114. if(wTemp == NULL)
  115. return NoMemory;
  116. wcsncpy(wTemp, pwcStart, pwcEnd-pwcStart);
  117. wTemp[pwcEnd-pwcStart] = 0;
  118. m_pOutput->SetServer(wTemp);
  119. delete wTemp;
  120. pRawPath = pwcEnd;
  121. }
  122. }
  123. // Point the lexer at the source.
  124. // ==============================
  125. CTextLexSource src((LPWSTR)pRawPath);
  126. m_pLexer = new CGenLexer(UMIPath_LexTable, &src);
  127. if(m_pLexer == NULL)
  128. return NoMemory;
  129. // Go.
  130. // ===
  131. int nRes = begin_parse(bRelative);
  132. if (nRes)
  133. {
  134. return nRes;
  135. }
  136. if (m_nCurrentToken != UMIPATH_TOK_EOF)
  137. {
  138. return SyntaxError;
  139. }
  140. // todo, check the following conditions
  141. /* if (m_pOutput->GetNumComponents() > 0 && !m_pOutput->HasServer())
  142. {
  143. if (m_eFlags != WBEMPATH_CREATE_ACCEPT_RELATIVE && m_eFlags != WBEMPATH_CREATE_ACCEPT_ALL)
  144. {
  145. return SyntaxError;
  146. }
  147. else
  148. {
  149. // Local namespace --- set server to "."
  150. // =====================================
  151. m_pOutput->SetServer(L".", true);
  152. }
  153. }
  154. */
  155. // m_pOutput->SortKeys(); //?? todo, is this applicable?
  156. // Add in key refs.
  157. // ================
  158. return NoError;
  159. }
  160. BOOL CUmiPathParser::NextToken()
  161. {
  162. m_nCurrentToken = m_pLexer->NextToken();
  163. if (m_nCurrentToken == UMIPATH_TOK_ERROR)
  164. return FALSE;
  165. return TRUE;
  166. }
  167. //
  168. //<umi_path> ::= UMICONST FSLASH FSLASH <locator> FSLASH <ns_root_selector> FSLASH
  169. // <component_list>;
  170. //
  171. int CUmiPathParser::begin_parse(bool bRelative)
  172. {
  173. // note that the locator is parsed manually in the calling routine.
  174. if (!NextToken())
  175. return SyntaxError;
  176. // get the root namespace
  177. if(!bRelative)
  178. {
  179. if(m_nCurrentToken != UMIPATH_TOK_FORWARDSLASH)
  180. return SyntaxError;
  181. if (!NextToken())
  182. return SyntaxError;
  183. int iRet = ns_root_selector();
  184. if(iRet)
  185. return iRet;
  186. // get the next forward slash. Note that ns_root_selector will have advanced the token
  187. if (m_nCurrentToken == UMIPATH_TOK_EOF) // take care of minimal case
  188. return 0;
  189. if (m_nCurrentToken != UMIPATH_TOK_FORWARDSLASH)
  190. return SyntaxError;
  191. if (!NextToken())
  192. return SyntaxError;
  193. }
  194. return component_list();
  195. }
  196. //
  197. // <locator> ::= IDENT ; // Machine name
  198. // <locator> ::= SERVERNAME ; // [Machine name]
  199. // <locator> ::= DOT ; // current machine name
  200. // <locator> ::= <>; // Machine name
  201. //
  202. int CUmiPathParser::locator()
  203. {
  204. if (!NextToken())
  205. return SyntaxError;
  206. // if forward slash, then no server was specified.
  207. if (m_nCurrentToken == UMIPATH_TOK_FORWARDSLASH)
  208. {
  209. return 0;
  210. }
  211. if (m_nCurrentToken == UMIPATH_TOK_DOT)
  212. m_pOutput->SetServer(L".");
  213. else if(m_nCurrentToken == UMIPATH_TOK_IDENT ||
  214. m_nCurrentToken == UMIPATH_TOK_SERVERNAME)
  215. m_pOutput->SetServer(m_pLexer->GetTokenText());
  216. else
  217. return SyntaxError;
  218. if(NextToken())
  219. return 0;
  220. else
  221. return SyntaxError;
  222. }
  223. //
  224. // <ns_root_selector> ::= IDENT;
  225. //
  226. int CUmiPathParser::ns_root_selector()
  227. {
  228. // This just expects the initial namespace.
  229. if (m_nCurrentToken != UMIPATH_TOK_IDENT)
  230. return SyntaxError;
  231. HRESULT hr = m_pOutput->SetNamespaceAt(0, m_pLexer->GetTokenText());
  232. if(FAILED(hr))
  233. return NoMemory;
  234. if(NextToken())
  235. return 0;
  236. else
  237. return SyntaxError;
  238. }
  239. //
  240. // <component_list> ::= <component><component_list_rest>;
  241. //
  242. int CUmiPathParser::component_list()
  243. {
  244. int iRet = component();
  245. if(iRet)
  246. return iRet;
  247. return component_list_rest();
  248. }
  249. //
  250. // <component_list_rest> ::= FSLASH <component><component_list_rest>;
  251. // <component_list_rest> ::= <>;
  252. //
  253. int CUmiPathParser::component_list_rest()
  254. {
  255. if (m_nCurrentToken == UMIPATH_TOK_EOF)
  256. return 0;
  257. if (m_nCurrentToken == UMIPATH_TOK_FORWARDSLASH)
  258. {
  259. if (!NextToken())
  260. return SyntaxError;
  261. if(component())
  262. return SyntaxError;
  263. else
  264. return component_list_rest();
  265. }
  266. else
  267. return SyntaxError;
  268. }
  269. //
  270. // <component> ::= IDENT <def_starts_with_ident>;
  271. // <component> ::= DOT <key_list>;
  272. // <component> ::= <GUID_PATH>;
  273. int CUmiPathParser::component()
  274. {
  275. CParsedComponent * pComp = new CParsedComponent(m_pOutput->GetRefCntCS()); // has ref count of 1
  276. if(pComp == NULL)
  277. return NoMemory;
  278. CReleaseMe rm(pComp); // Is addrefed if all is well.
  279. int iRet;
  280. if (m_nCurrentToken == UMIPATH_TOK_DOT)
  281. {
  282. if (!NextToken())
  283. return SyntaxError;
  284. iRet = key_list(pComp);
  285. if(iRet == 0)
  286. {
  287. if(SUCCEEDED(m_pOutput->AddComponent(pComp)))
  288. pComp->AddRef();
  289. }
  290. return iRet;
  291. }
  292. // a guid path looks like an ident to the parser
  293. if (m_nCurrentToken != UMIPATH_TOK_IDENT)
  294. {
  295. return SyntaxError;
  296. }
  297. if(!_wcsnicmp( m_pLexer->GetTokenText(), L"<GUID>={", 8))
  298. {
  299. iRet = guid_path(pComp);
  300. }
  301. else
  302. {
  303. WCHAR * pTemp = new WCHAR[wcslen(m_pLexer->GetTokenText()) + 1];
  304. if(pTemp == NULL)
  305. return NoMemory;
  306. wcscpy(pTemp, m_pLexer->GetTokenText());
  307. iRet = def_starts_with_ident(pTemp, pComp);
  308. delete pTemp;
  309. }
  310. if(iRet == 0)
  311. if(SUCCEEDED(m_pOutput->AddComponent(pComp)))
  312. pComp->AddRef();
  313. return iRet;
  314. }
  315. //
  316. // <def_starts_with_ident> ::= DOT <key_list>;
  317. // <def_starts_with_ident> ::= TOK_EQUALS IDENT;
  318. // <def_starts_with_ident> ::= <>;
  319. //
  320. int CUmiPathParser::def_starts_with_ident(LPWSTR pwsLeadingName, CParsedComponent * pComp)
  321. {
  322. int iRet = 0;
  323. if (!NextToken())
  324. return SyntaxError;
  325. if (m_nCurrentToken == UMIPATH_TOK_DOT)
  326. {
  327. pComp->m_sClassName = SysAllocString(pwsLeadingName);
  328. if(pComp->m_sClassName == NULL)
  329. return NoMemory;
  330. if (!NextToken())
  331. return SyntaxError;
  332. return key_list(pComp);
  333. }
  334. if (m_nCurrentToken == UMIPATH_TOK_EQ)
  335. {
  336. pComp->m_sClassName = SysAllocString(pwsLeadingName);
  337. if(pComp->m_sClassName == NULL)
  338. return NoMemory;
  339. if (!NextToken())
  340. return SyntaxError;
  341. if(m_nCurrentToken == UMIPATH_TOK_IDENT)
  342. iRet = pComp->SetKey(NULL, 0, CIM_STRING, m_pLexer->GetTokenText());
  343. else if(m_nCurrentToken == UMIPATH_TOK_SINGLETON_SYM)
  344. pComp->MakeSingleton(true);
  345. else
  346. return SyntaxError;
  347. if (!NextToken())
  348. return SyntaxError;
  349. return iRet;
  350. }
  351. else
  352. {
  353. pComp->m_sClassName = SysAllocString(pwsLeadingName);
  354. if(pComp->m_sClassName == NULL)
  355. return NoMemory;
  356. else
  357. return 0;
  358. }
  359. }
  360. // <guid_path> ::= TOK_GUILD_CONST TOK_GUID;
  361. int CUmiPathParser::guid_path(CParsedComponent * pComp)
  362. {
  363. LPWSTR pTemp = m_pLexer->GetTokenText();
  364. if(!_wcsnicmp( m_pLexer->GetTokenText(), L"<GUID>={", 8))
  365. {
  366. // got a guid. try doing a converstion just to check the syntax.
  367. UUID Uuid;
  368. HRESULT hr = UuidFromString(pTemp+7, &Uuid);
  369. if(FAILED(hr))
  370. return SyntaxError;
  371. }
  372. HRESULT hr = pComp->SetNS(m_pLexer->GetTokenText());
  373. if(FAILED(hr))
  374. return NoMemory;
  375. else
  376. return 0;
  377. }
  378. //
  379. // <key_list> ::= <key><key_list_rest>;
  380. //
  381. int CUmiPathParser::key_list(CParsedComponent * pComp)
  382. {
  383. int iRet = key(pComp);
  384. if(iRet)
  385. return iRet;
  386. else
  387. return key_list_rest(pComp);
  388. }
  389. //
  390. // <key_list_rest> ::= TOK_COMMA <key><key_list_rest>;
  391. // <key_list_rest> ::= <>;
  392. //
  393. int CUmiPathParser::key_list_rest(CParsedComponent * pComp)
  394. {
  395. if (!NextToken())
  396. return SyntaxError;
  397. if (m_nCurrentToken == UMIPATH_TOK_COMMA)
  398. {
  399. if (!NextToken())
  400. return SyntaxError;
  401. int iRet = key(pComp);
  402. if(iRet)
  403. return iRet;
  404. else
  405. return key_list_rest(pComp);
  406. }
  407. return 0;
  408. }
  409. //
  410. // <key> ::= IDENT TOK_EQUALS IDENT;
  411. //
  412. int CUmiPathParser::key(CParsedComponent * pComp)
  413. {
  414. if(m_nCurrentToken != UMIPATH_TOK_IDENT)
  415. return SyntaxError;
  416. LPWSTR pKeyName = new WCHAR[wcslen(m_pLexer->GetTokenText())+1];
  417. if(pKeyName == NULL)
  418. return NoMemory;
  419. CDeleteMe<WCHAR> dm(pKeyName);
  420. wcscpy(pKeyName,m_pLexer->GetTokenText());
  421. if (!NextToken())
  422. return SyntaxError;
  423. if(m_nCurrentToken != UMIPATH_TOK_EQ)
  424. return SyntaxError;
  425. if (!NextToken())
  426. return SyntaxError;
  427. if(m_nCurrentToken != UMIPATH_TOK_IDENT)
  428. return SyntaxError;
  429. return pComp->SetKey(pKeyName, 0, CIM_STRING, m_pLexer->GetTokenText());
  430. }
  431. HRESULT CDefPathParser::Set(
  432. /* [in] */ long lFlags,
  433. /* [in] */ LPCWSTR pszText)
  434. {
  435. //todo, look at the flags. Note that this can get redirected wmi calls.
  436. CSafeInCritSec cs(m_pCS->GetCS());
  437. if(!cs.IsOK())
  438. return WBEM_E_OUT_OF_MEMORY;
  439. if(pszText == NULL)
  440. return WBEM_E_INVALID_PARAMETER;
  441. if(!IsEmpty())
  442. Empty();
  443. m_bSetViaUMIPath = true;
  444. // special hack for Raja
  445. if(lFlags & 0x8000)
  446. {
  447. int iLen = wcslen(pszText) + 1;
  448. m_pRawPath = new WCHAR[iLen];
  449. if(m_pRawPath == NULL)
  450. return WBEM_E_OUT_OF_MEMORY;
  451. wcscpy(m_pRawPath, pszText);
  452. return S_OK;
  453. }
  454. // end of special hack for Raja
  455. CUmiPathParser parser(0);
  456. int iRet = parser.Parse(pszText, *this);
  457. if(iRet == 0)
  458. {
  459. // the parser doesnt know scopes from class. So, make the last
  460. // scope the class.
  461. m_dwStatus = OK;
  462. return S_OK;
  463. }
  464. else
  465. {
  466. m_dwStatus = BAD_STRING;
  467. return WBEM_E_INVALID_PARAMETER;
  468. }
  469. }
  470. HRESULT CDefPathParser::Get(
  471. /* [in] */ long lFlags,
  472. /* [out][in] */ ULONG __RPC_FAR *puBufSize,
  473. /* [string][in] */ LPWSTR pszDest)
  474. {
  475. CSafeInCritSec cs(m_pCS->GetCS());
  476. if(!cs.IsOK())
  477. return WBEM_E_OUT_OF_MEMORY;
  478. if(puBufSize == NULL)
  479. return WBEM_E_INVALID_PARAMETER;
  480. // special hack for Raja
  481. if(m_pRawPath)
  482. {
  483. DWORD dwSizeNeeded = wcslen(m_pRawPath) + 1;
  484. DWORD dwBuffSize = *puBufSize;
  485. *puBufSize = dwSizeNeeded;
  486. if(pszDest)
  487. {
  488. if(dwSizeNeeded > dwBuffSize)
  489. return WBEM_E_BUFFER_TOO_SMALL;
  490. wcscpy(pszDest, m_pRawPath);
  491. }
  492. return S_OK;
  493. }
  494. // special hack for Raja
  495. // determine how big the buffer needs to be.
  496. // an example path is "umi://h27pjr/root/st";
  497. DWORD dwSc = m_Components.Size();
  498. int iSize = 1; // 1 for the null terminator
  499. if(m_pServer)
  500. {
  501. iSize += 7; // counts for umi: and first three slashes and null
  502. iSize += wcslen(m_pServer);
  503. }
  504. DWORD dwNumComp = GetNumComponents();
  505. for(DWORD dwCnt = 0; dwCnt < dwNumComp; dwCnt++)
  506. {
  507. bool bNeedEqual = false;
  508. CParsedComponent * pObj;
  509. if(dwCnt < (dwSc))
  510. pObj = (CParsedComponent *)m_Components[dwCnt];
  511. else
  512. break;
  513. if(pObj->m_sClassName)
  514. {
  515. iSize += wcslen(pObj->m_sClassName);
  516. bNeedEqual = true;
  517. }
  518. DWORD dwNumKey = 0;
  519. pObj->GetCount(&dwNumKey);
  520. for(DWORD dwKey = 0; dwKey < dwNumKey; dwKey++)
  521. {
  522. CKeyRef * pKey = (CKeyRef *)pObj->m_Keys.GetAt(dwKey);
  523. if(pKey->m_pName && wcslen(pKey->m_pName))
  524. {
  525. iSize += wcslen(pKey->m_pName);
  526. if(dwKey == 0)
  527. iSize++; // 1 is for the dot.
  528. bNeedEqual = true;
  529. }
  530. if(pKey->m_dwSize)
  531. {
  532. LPWSTR pValue = pKey->GetValue(false);
  533. if(pValue)
  534. {
  535. iSize+= wcslen(pValue);
  536. delete pValue;
  537. }
  538. if(bNeedEqual)
  539. iSize++;
  540. }
  541. if(dwKey < dwNumKey-1)
  542. iSize++; // one for the comma!
  543. }
  544. if(dwCnt < dwNumComp-1)
  545. iSize++; // one for the slash
  546. }
  547. // If caller is just looking for size, return now
  548. if(pszDest == NULL)
  549. {
  550. *puBufSize = iSize;
  551. return S_OK;
  552. }
  553. DWORD dwBuffSize = *puBufSize;
  554. *puBufSize = iSize;
  555. if((DWORD)iSize > dwBuffSize)
  556. return WBEM_E_BUFFER_TOO_SMALL;
  557. if(m_pServer)
  558. {
  559. wcscpy(pszDest, L"umi://");
  560. if(m_pServer)
  561. wcscat(pszDest, m_pServer);
  562. wcscat(pszDest, L"/");
  563. }
  564. else
  565. *pszDest = 0;
  566. for(DWORD dwCnt = 0; dwCnt < dwNumComp; dwCnt++)
  567. {
  568. bool bNeedEqual = false;
  569. CParsedComponent * pObj;
  570. if(dwCnt < (dwSc))
  571. pObj = (CParsedComponent *)m_Components[dwCnt];
  572. else
  573. break;
  574. if(pObj->m_sClassName)
  575. {
  576. wcscat(pszDest,pObj->m_sClassName);
  577. bNeedEqual = true;
  578. }
  579. DWORD dwNumKey = 0;
  580. pObj->GetCount(&dwNumKey);
  581. for(DWORD dwKey = 0; dwKey < dwNumKey; dwKey++)
  582. {
  583. CKeyRef * pKey = (CKeyRef *)pObj->m_Keys.GetAt(dwKey);
  584. if(pKey->m_pName && wcslen(pKey->m_pName))
  585. {
  586. if(dwKey == 0)
  587. wcscat(pszDest,L".");
  588. wcscat(pszDest,pKey->m_pName); // 1 is for the dot.
  589. bNeedEqual = true;
  590. }
  591. if(pKey->m_dwSize)
  592. {
  593. if(bNeedEqual)
  594. wcscat(pszDest,L"=");
  595. LPWSTR pValue = pKey->GetValue(false);
  596. if(pValue)
  597. {
  598. wcscat(pszDest, pValue);
  599. delete pValue;
  600. }
  601. }
  602. if(dwKey < dwNumKey-1)
  603. wcscat(pszDest, L","); // one for the comma!
  604. }
  605. if(dwCnt < dwNumComp-1)
  606. wcscat(pszDest, L"/"); // one for the slash
  607. }
  608. return S_OK;
  609. }
  610. HRESULT CDefPathParser::GetPathInfo(
  611. /* [in] */ ULONG uRequestedInfo,
  612. /* [out] */ ULONGLONG __RPC_FAR *puResponse)
  613. {
  614. CSafeInCritSec cs(m_pCS->GetCS());
  615. if(!cs.IsOK())
  616. return WBEM_E_OUT_OF_MEMORY;
  617. if(uRequestedInfo != 0 || puResponse == NULL)
  618. return WBEM_E_INVALID_PARAMETER;
  619. *puResponse = NULL;
  620. if(m_pRawPath)
  621. *puResponse |= UMIPATH_INFO_NATIVE_STRING;
  622. else if(m_pServer == NULL)
  623. *puResponse |= UMIPATH_INFO_RELATIVE_PATH;
  624. if(m_Components.Size() > 0)
  625. {
  626. int iSize = m_Components.Size();
  627. CParsedComponent * pComp = (CParsedComponent *)m_Components.GetAt(iSize-1);
  628. if(!pComp->IsPossibleNamespace())
  629. if(pComp->IsInstance())
  630. {
  631. *puResponse |= UMIPATH_INFO_INSTANCE_PATH;
  632. if(pComp->m_bSingleton)
  633. *puResponse |= UMIPATH_INFO_SINGLETON_PATH;
  634. }
  635. else
  636. *puResponse |= UMIPATH_INFO_CLASS_PATH;
  637. }
  638. return S_OK;
  639. }
  640. HRESULT CDefPathParser::SetLocator(
  641. /* [string][in] */ LPCWSTR Name)
  642. {
  643. return SetServer(Name); // mutex is grabbed here
  644. }
  645. HRESULT CDefPathParser::GetLocator(
  646. /* [out][in] */ ULONG __RPC_FAR *puNameBufLength,
  647. /* [string][in] */ LPWSTR pName)
  648. {
  649. return GetServer(puNameBufLength, pName); // mutex is grabbed here
  650. }
  651. HRESULT CDefPathParser::SetRootNamespace(
  652. /* [string][in] */ LPCWSTR Name)
  653. {
  654. CSafeInCritSec cs(m_pCS->GetCS());
  655. if(!cs.IsOK())
  656. return WBEM_E_OUT_OF_MEMORY;
  657. if(Name == NULL)
  658. return WBEM_E_INVALID_PARAMETER;
  659. if(m_Components.Size() > 0)
  660. RemoveNamespaceAt(0);
  661. return SetNamespaceAt(0, Name);
  662. }
  663. HRESULT CDefPathParser::GetRootNamespace(
  664. /* [out][in] */ ULONG __RPC_FAR *puNameBufLength,
  665. /* [string][out][in] */ LPWSTR pName)
  666. {
  667. CSafeInCritSec cs(m_pCS->GetCS());
  668. if(!cs.IsOK())
  669. return WBEM_E_OUT_OF_MEMORY;
  670. return GetNamespaceAt(0, puNameBufLength, pName);
  671. }
  672. HRESULT CDefPathParser::GetComponentCount(
  673. /* [out] */ ULONG __RPC_FAR *puCount)
  674. {
  675. CSafeInCritSec cs(m_pCS->GetCS());
  676. if(!cs.IsOK())
  677. return WBEM_E_OUT_OF_MEMORY;
  678. if(puCount == 0)
  679. return WBEM_E_INVALID_PARAMETER;
  680. *puCount = m_Components.Size()-1; // dont count root namespace
  681. return S_OK;
  682. }
  683. HRESULT CDefPathParser::SetComponent(
  684. /* [in] */ ULONG uIndex,
  685. /* [in] */ LPWSTR pszClass)
  686. {
  687. CSafeInCritSec cs(m_pCS->GetCS());
  688. if(!cs.IsOK())
  689. return WBEM_E_OUT_OF_MEMORY;
  690. DWORD dwNumComp = m_Components.Size()-1; // dont count root namespace
  691. if(uIndex > dwNumComp)
  692. return WBEM_E_INVALID_PARAMETER;
  693. CParsedComponent * pNew = new CParsedComponent(m_pCS);
  694. if(pNew == NULL)
  695. return WBEM_E_OUT_OF_MEMORY;
  696. if(pszClass)
  697. {
  698. pNew->m_sClassName = SysAllocString(pszClass);
  699. if(pNew->m_sClassName == NULL)
  700. {
  701. delete pNew;
  702. return WBEM_E_OUT_OF_MEMORY;
  703. }
  704. }
  705. int iRet = m_Components.InsertAt(uIndex + 1, pNew);
  706. if(iRet == CFlexArray::no_error)
  707. return S_OK;
  708. else
  709. {
  710. delete pNew;
  711. return WBEM_E_OUT_OF_MEMORY;
  712. }
  713. }
  714. HRESULT CDefPathParser::SetComponentFromText(
  715. /* [in] */ ULONG uIndex,
  716. /* [in] */ LPWSTR pszText)
  717. {
  718. CSafeInCritSec cs(m_pCS->GetCS());
  719. if(!cs.IsOK())
  720. return WBEM_E_OUT_OF_MEMORY;
  721. return WBEM_E_NOT_AVAILABLE;
  722. }
  723. HRESULT CDefPathParser::GetComponent(
  724. /* [in] */ ULONG uIndex,
  725. /* [out][in] */ ULONG __RPC_FAR *puClassNameBufSize,
  726. /* [out][in] */ LPWSTR pszClass,
  727. /* [out] */ IUmiURLKeyList __RPC_FAR *__RPC_FAR *pKeyList)
  728. {
  729. CSafeInCritSec cs(m_pCS->GetCS());
  730. if(!cs.IsOK())
  731. return WBEM_E_OUT_OF_MEMORY;
  732. uIndex++; // skip root ns
  733. if(uIndex >= (DWORD)m_Components.Size())
  734. return WBEM_E_INVALID_PARAMETER;
  735. CParsedComponent * pComp = (CParsedComponent *)m_Components.GetAt(uIndex);
  736. DWORD dwSize = 0;
  737. if(pComp->m_sClassName)
  738. dwSize = wcslen(pComp->m_sClassName)+1;
  739. DWORD dwBuffSize = *puClassNameBufSize;
  740. if(puClassNameBufSize)
  741. {
  742. *puClassNameBufSize = dwSize;
  743. if(dwBuffSize > 0 && pszClass)
  744. pszClass[0] = NULL;
  745. }
  746. if(pComp->m_sClassName && pszClass)
  747. {
  748. if(dwSize > dwBuffSize)
  749. return WBEM_E_BUFFER_TOO_SMALL;
  750. else
  751. wcscpy(pszClass, pComp->m_sClassName);
  752. }
  753. if(pKeyList)
  754. {
  755. return pComp->QueryInterface(IID_IUmiURLKeyList, (void **)pKeyList);
  756. }
  757. return S_OK;
  758. }
  759. HRESULT CDefPathParser::GetComponentAsText(
  760. /* [in] */ ULONG uIndex,
  761. /* [out][in] */ ULONG __RPC_FAR *puTextBufSize,
  762. /* [out][in] */ LPWSTR pszText)
  763. {
  764. CSafeInCritSec cs(m_pCS->GetCS());
  765. if(!cs.IsOK())
  766. return WBEM_E_OUT_OF_MEMORY;
  767. return WBEM_E_NOT_AVAILABLE;
  768. }
  769. HRESULT CDefPathParser::RemoveComponent(
  770. /* [in] */ ULONG uIndex)
  771. {
  772. CSafeInCritSec cs(m_pCS->GetCS());
  773. if(!cs.IsOK())
  774. return WBEM_E_OUT_OF_MEMORY;
  775. uIndex++; // skip root ns
  776. if(uIndex >= (DWORD)m_Components.Size())
  777. return WBEM_E_INVALID_PARAMETER;
  778. CParsedComponent * pComp = (CParsedComponent *)m_Components.GetAt(uIndex);
  779. pComp->Release();
  780. m_Components.RemoveAt(uIndex);
  781. return S_OK;
  782. }
  783. HRESULT CDefPathParser::RemoveAllComponents( void)
  784. {
  785. CSafeInCritSec cs(m_pCS->GetCS());
  786. if(!cs.IsOK())
  787. return WBEM_E_OUT_OF_MEMORY;
  788. for (DWORD dwIx = (DWORD)m_Components.Size()-1; dwIx > 0 ; dwIx--)
  789. {
  790. CParsedComponent * pCom = (CParsedComponent *)m_Components[dwIx];
  791. pCom->Release();
  792. m_Components.RemoveAt(dwIx);
  793. }
  794. return S_OK;
  795. }
  796. HRESULT CDefPathParser::SetLeafName(
  797. /* [string][in] */ LPCWSTR Name)
  798. {
  799. return SetClassName(Name); // mutex is grabbed here
  800. }
  801. HRESULT CDefPathParser::GetLeafName(
  802. /* [out][in] */ ULONG __RPC_FAR *puBuffLength,
  803. /* [string][out][in] */ LPWSTR pszName)
  804. {
  805. return GetClassName(puBuffLength, pszName); // mutex is grabbed here
  806. }
  807. HRESULT CDefPathParser::GetKeyList(
  808. /* [out] */ IUmiURLKeyList __RPC_FAR *__RPC_FAR *pOut)
  809. {
  810. CSafeInCritSec cs(m_pCS->GetCS());
  811. if(!cs.IsOK())
  812. return WBEM_E_OUT_OF_MEMORY;
  813. CParsedComponent * pClass = GetClass();
  814. HRESULT hRes = WBEM_E_NOT_AVAILABLE;
  815. if(pOut == NULL || pClass == NULL)
  816. return WBEM_E_INVALID_PARAMETER;
  817. hRes = pClass->QueryInterface(IID_IUmiURLKeyList, (void **)pOut);
  818. return hRes;
  819. }
  820. HRESULT CDefPathParser::CreateLeafPart(
  821. /* [in] */ long lFlags,
  822. /* [string][in] */ LPCWSTR Name)
  823. {
  824. return CreateClassPart(lFlags, Name); // mutex is grabbed here
  825. }
  826. HRESULT CDefPathParser::DeleteLeafPart(
  827. /* [in] */ long lFlags)
  828. {
  829. return DeleteClassPart(lFlags); // mutex is grabbed here
  830. }
  831. HRESULT CUmiParsedComponent::GetKey( /* [in] */ ULONG uKeyIx,
  832. /* [in] */ ULONG uFlags,
  833. /* [out][in] */ ULONG __RPC_FAR *puKeyNameBufSize,
  834. /* [in] */ LPWSTR pszKeyName,
  835. /* [out][in] */ ULONG __RPC_FAR *puValueBufSize,
  836. /* [in] */ LPWSTR pszValue)
  837. {
  838. //fix in blackcomb CSafeInCritSec cs(m_pOutput->GetRefCntCS()->GetCS());
  839. if(puValueBufSize)
  840. *puValueBufSize *= 2;
  841. return m_pParent->GetKey(uKeyIx, WBEMPATH_TEXT,puKeyNameBufSize,pszKeyName,puValueBufSize,
  842. pszValue, NULL);
  843. }