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.

3112 lines
64 KiB

  1. /*++
  2. // Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. PathParse.CPP
  5. Abstract:
  6. Implements the default object path parser/
  7. History:
  8. a-davj 6-feb-00 Created.
  9. --*/
  10. #include "precomp.h"
  11. #include <genlex.h>
  12. //#include <opathlex.h>
  13. #include <string.h>
  14. #include "PathParse.h"
  15. #include "ActualParse.h"
  16. #include "commain.h"
  17. //#include "resource.h"
  18. #include "wbemcli.h"
  19. #include <stdio.h>
  20. #include <sync.h>
  21. #include "helpers.h"
  22. CRefCntCS::CRefCntCS()
  23. {
  24. m_lRef = 1;
  25. m_Status = S_OK;
  26. m_guard1 = 0x52434353;
  27. m_guard2 = 0x52434353;
  28. __try
  29. {
  30. InitializeCriticalSection(&m_cs);
  31. }
  32. __except(1)
  33. {
  34. m_Status = WBEM_E_OUT_OF_MEMORY;
  35. }
  36. }
  37. long CRefCntCS::Release()
  38. {
  39. long lRet = InterlockedDecrement(&m_lRef);
  40. if(lRet == 0)
  41. delete this;
  42. return lRet;
  43. }
  44. bool Equal(LPCWSTR first, LPCWSTR second, DWORD dwLen)
  45. {
  46. if(first == NULL || second == NULL)
  47. return false;
  48. if(wcslen(first) < dwLen || wcslen(second) < dwLen)
  49. return false;
  50. for (DWORD dwCnt = 0; dwCnt < dwLen; dwCnt++, first++, second++)
  51. {
  52. if(towupper(*first) != towupper(*second))
  53. return false;
  54. }
  55. return true;
  56. }
  57. /*++
  58. Routine Description:
  59. Determines the number of bytes needed to store data
  60. Arguments:
  61. uCimType - Cim type
  62. pKyeValue - pointer to data to be stored
  63. Return Value:
  64. Number of bytes. 0 if an error
  65. --*/
  66. DWORD GetCIMSize(DWORD uCimType, void * pKeyVal)
  67. {
  68. DWORD dwRet = 0;
  69. switch(uCimType)
  70. {
  71. case CIM_STRING:
  72. case CIM_REFERENCE:
  73. case CIM_DATETIME:
  74. dwRet = 2 * (wcslen((WCHAR *)pKeyVal) + 1);
  75. break;
  76. case CIM_UINT8:
  77. case CIM_SINT8:
  78. dwRet = 1;
  79. break;
  80. case CIM_SINT16:
  81. case CIM_UINT16:
  82. case CIM_CHAR16:
  83. dwRet = 2;
  84. break;
  85. case CIM_SINT32:
  86. case CIM_UINT32:
  87. case CIM_BOOLEAN:
  88. dwRet = 4;
  89. break;
  90. case CIM_SINT64:
  91. case CIM_UINT64:
  92. dwRet = 8;
  93. break;
  94. }
  95. return dwRet;
  96. }
  97. //***************************************************************************
  98. //
  99. // CKeyRef Class. Used to store a key name/value pair
  100. //
  101. //***************************************************************************
  102. /*++
  103. Routine Description:
  104. Default Constructor.
  105. --*/
  106. CKeyRef::CKeyRef()
  107. {
  108. m_pName = 0;
  109. m_dwType = CIM_EMPTY;
  110. m_dwSize = 0;
  111. m_pData = NULL;
  112. }
  113. /*++
  114. Routine Description:
  115. Constructor.
  116. Arguments:
  117. wszKeyName - name
  118. dwType - cim type
  119. dwSize - data size
  120. pData - actual data
  121. --*/
  122. CKeyRef::CKeyRef(LPCWSTR wszKeyName, DWORD dwType, DWORD dwSize, void * pData)
  123. {
  124. if(wszKeyName)
  125. m_pName = Macro_CloneLPWSTR(wszKeyName);
  126. else
  127. m_pName = NULL;
  128. m_pData = NULL;
  129. SetData(dwType, dwSize, pData);
  130. }
  131. /*++
  132. Routine Description:
  133. Sets the data for a CKeyRef object. Frees any existing data.
  134. Arguments:
  135. dwType - cim type
  136. dwSize - data size
  137. pData - actual data
  138. Return Value:
  139. S_OK if all is well.
  140. WBEM_E_INVALID_PARAMETER if bad arg
  141. WBEM_E_OUT_OF_MEMORY if low memory problem
  142. --*/
  143. HRESULT CKeyRef::SetData(DWORD dwType, DWORD dwSize, void * pData)
  144. {
  145. if(m_pData)
  146. delete m_pData;
  147. m_pData = NULL;
  148. m_dwType = CIM_EMPTY;
  149. m_dwSize = 0;
  150. if(dwSize && pData && GetCIMSize(dwType, pData))
  151. {
  152. m_pData = new byte[dwSize];
  153. if(m_pData)
  154. {
  155. m_dwType = dwType;
  156. m_dwSize = dwSize;
  157. memcpy(m_pData, pData, dwSize);
  158. return S_OK;
  159. }
  160. return WBEM_E_OUT_OF_MEMORY;
  161. }
  162. else
  163. return WBEM_E_INVALID_PARAMETER;
  164. }
  165. /*++
  166. Routine Description:
  167. Destructor.
  168. --*/
  169. CKeyRef::~CKeyRef()
  170. {
  171. if (m_pName)
  172. delete m_pName;
  173. if (m_pData)
  174. delete m_pData;
  175. }
  176. /*++
  177. Routine Description:
  178. provide an estimate of how large the value could be once converted to
  179. a character string.
  180. Return Value:
  181. Limit on how many bytes are needed.
  182. --*/
  183. DWORD CKeyRef::GetValueSize()
  184. {
  185. if(m_dwType == CIM_STRING || m_dwType == CIM_REFERENCE || m_dwType == CIM_DATETIME)
  186. return m_dwSize * 2 + 2;
  187. else if(m_dwSize == 8)
  188. return 21;
  189. else
  190. return 14;
  191. }
  192. /*++
  193. Routine Description:
  194. Returns estimate of how large the key/value pair may be.
  195. --*/
  196. DWORD CKeyRef::GetTotalSize()
  197. {
  198. DWORD dwSize = GetValueSize();
  199. if (m_pName)
  200. dwSize += wcslen(m_pName) +1;
  201. return dwSize;
  202. }
  203. /*++
  204. Routine Description:
  205. Returns the value as text.
  206. Arguments:
  207. bQuotes - If true, the strings are enclosed in quotes
  208. Return Value:
  209. Pointer to string. Caller must free via delete. NULL if error.
  210. --*/
  211. LPWSTR CKeyRef::GetValue(BOOL bQuotes)
  212. {
  213. LPWSTR lpKey = NULL;
  214. DWORD dwSize, dwCnt;
  215. WCHAR * pFr, * pTo;
  216. unsigned __int64 * pull;
  217. pFr = (WCHAR *)m_pData;
  218. // For string, the size may need to be increaed for quotes
  219. if(m_dwType == CIM_STRING || m_dwType == CIM_REFERENCE)
  220. {
  221. dwSize = m_dwSize;
  222. if(bQuotes)
  223. dwSize+= 2;
  224. }
  225. else
  226. dwSize = 32;
  227. lpKey = new WCHAR[dwSize];
  228. if(lpKey == NULL)
  229. return NULL;
  230. switch(m_dwType)
  231. {
  232. case CIM_STRING:
  233. case CIM_REFERENCE:
  234. pTo = lpKey;
  235. if (bQuotes && m_dwType == CIM_STRING)
  236. {
  237. *pTo = '"';
  238. pTo++;
  239. }
  240. for(dwCnt = 0; dwCnt < m_dwSize && *pFr; dwCnt++, pFr++, pTo++)
  241. {
  242. if(*pFr == '\\' || *pFr == '"')
  243. {
  244. *pTo = '\\';
  245. pTo++;
  246. }
  247. *pTo = *pFr;
  248. }
  249. if (bQuotes && m_dwType == CIM_STRING)
  250. {
  251. *pTo = '"';
  252. pTo++;
  253. }
  254. *pTo = 0;
  255. break;
  256. case CIM_SINT32:
  257. swprintf(lpKey, L"%d", *(int *)m_pData);
  258. break;
  259. case CIM_UINT32:
  260. swprintf(lpKey, L"%u", *(unsigned *)m_pData);
  261. break;
  262. case CIM_SINT16:
  263. swprintf(lpKey, L"%hd", *(signed short *)m_pData);
  264. break;
  265. case CIM_UINT16:
  266. swprintf(lpKey, L"%hu", *(unsigned short *)m_pData);
  267. break;
  268. case CIM_SINT8:
  269. swprintf(lpKey, L"%d", *(signed char *)m_pData);
  270. break;
  271. case CIM_UINT8:
  272. swprintf(lpKey, L"%u", *(unsigned char *)m_pData);
  273. break;
  274. case CIM_UINT64:
  275. swprintf(lpKey, L"%I64u", *(unsigned __int64 *)m_pData);
  276. break;
  277. case CIM_SINT64:
  278. swprintf(lpKey, L"%I64d", *(__int64 *)m_pData);
  279. break;
  280. case CIM_BOOLEAN:
  281. if(*(int *)m_pData == 0)
  282. wcscpy(lpKey,L"false");
  283. else
  284. wcscpy(lpKey,L"true");
  285. break;
  286. default:
  287. *lpKey = 0;
  288. break;
  289. }
  290. return lpKey;
  291. }
  292. //***************************************************************************
  293. //
  294. // CParsedComponent
  295. //
  296. //***************************************************************************
  297. /*++
  298. Routine Description:
  299. Constructor.
  300. --*/
  301. CParsedComponent::CParsedComponent(CRefCntCS * pCS)
  302. {
  303. m_bSingleton = false;
  304. m_cRef = 1;
  305. m_sClassName = NULL;
  306. m_pCS = pCS;
  307. if(m_pCS)
  308. m_pCS->AddRef();
  309. //// m_UmiWrapper.Set(m_hMutex);
  310. m_pFTM = NULL;
  311. CoCreateFreeThreadedMarshaler((IWbemPath*)this, &m_pFTM);
  312. }
  313. /*++
  314. Routine Description:
  315. Destructor.
  316. --*/
  317. CParsedComponent::~CParsedComponent()
  318. {
  319. if(m_pCS)
  320. m_pCS->Release();
  321. ClearKeys();
  322. if(m_sClassName)
  323. SysFreeString(m_sClassName);
  324. m_pCS = NULL;
  325. if(m_pFTM)
  326. m_pFTM->Release();
  327. }
  328. /*++
  329. Routine Description:
  330. Retrieves the call name.
  331. Arguments:
  332. pName - Where the name is to be copied. Note that the call must free via SysFreeString
  333. Return Value:
  334. S_OK if all is well, else error
  335. --*/
  336. HRESULT CParsedComponent::GetName(BSTR *pName)
  337. {
  338. HRESULT hr = 0;
  339. if (pName == NULL || m_sClassName == NULL)
  340. return WBEM_E_INVALID_PARAMETER;
  341. *pName = SysAllocString(m_sClassName);
  342. if(*pName)
  343. return S_OK;
  344. else
  345. return WBEM_E_OUT_OF_MEMORY;
  346. }
  347. /*++
  348. Routine Description:
  349. returns the class/key info in standard format. Ex; class="hello" or
  350. class.key1=23,key2=[reference]
  351. Arguments:
  352. pOutputKey - Where the value is to be copied. Must be freed by the
  353. caller.
  354. Return Value:
  355. S_OK if all is well, else an error code
  356. --*/
  357. HRESULT CParsedComponent::Unparse(BSTR *pOutputKey, bool bGetQuotes, bool bUseClassName)
  358. {
  359. HRESULT hr = 0;
  360. if (pOutputKey)
  361. {
  362. int nSpace = 0;
  363. if(m_sClassName && bUseClassName)
  364. nSpace += wcslen(m_sClassName);
  365. nSpace += 10;
  366. DWORD dwIx;
  367. for (dwIx = 0; dwIx < (DWORD)m_Keys.Size(); dwIx++)
  368. {
  369. CKeyRef* pKey = (CKeyRef*)m_Keys[dwIx];
  370. nSpace += pKey->GetTotalSize();
  371. }
  372. LPWSTR wszPath = new WCHAR[nSpace];
  373. if(wszPath == NULL)
  374. return WBEM_E_OUT_OF_MEMORY;
  375. CDeleteMe<WCHAR> dm1(wszPath);
  376. wszPath[0] = 0;
  377. if(m_sClassName && bUseClassName)
  378. wcscpy(wszPath, (const wchar_t *)m_sClassName);
  379. if (m_bSingleton)
  380. if(bUseClassName)
  381. wcscat(wszPath, L"=@");
  382. else
  383. wcscat(wszPath, L"@");
  384. for (dwIx = 0; dwIx < (DWORD)m_Keys.Size(); dwIx++)
  385. {
  386. CKeyRef* pKey = (CKeyRef *)m_Keys[dwIx];
  387. // We dont want to put a '.' if there isnt a key name,
  388. // for example, Myclass="value"
  389. if(dwIx == 0)
  390. {
  391. if((pKey->m_pName && (0 < wcslen(pKey->m_pName))) || m_Keys.Size() > 1)
  392. if(bUseClassName)
  393. wcscat(wszPath, L".");
  394. }
  395. else
  396. {
  397. wcscat(wszPath, L",");
  398. }
  399. if(pKey->m_pName)
  400. {
  401. wcscat(wszPath, pKey->m_pName);
  402. }
  403. LPWSTR lpTemp = pKey->GetValue(bGetQuotes);
  404. if(lpTemp)
  405. {
  406. if(wcslen(wszPath))
  407. wcscat(wszPath, L"=");
  408. wcscat(wszPath, lpTemp);
  409. delete lpTemp;
  410. }
  411. }
  412. *pOutputKey = SysAllocString(wszPath);
  413. if (!(*pOutputKey))
  414. return WBEM_E_OUT_OF_MEMORY;
  415. }
  416. else
  417. hr = WBEM_E_INVALID_PARAMETER;
  418. return hr;
  419. }
  420. /*++
  421. Routine Description:
  422. Gets the number of keys.
  423. Arguments:
  424. puKeyCount - Where the result is to be put.
  425. Return Value:
  426. S_OK if all is well, else an error code.
  427. --*/
  428. HRESULT CParsedComponent::GetCount(
  429. /* [out] */ ULONG __RPC_FAR *puKeyCount)
  430. {
  431. CSafeInCritSec cs(m_pCS->GetCS());
  432. if(!cs.IsOK())
  433. return WBEM_E_OUT_OF_MEMORY;
  434. if(puKeyCount == NULL)
  435. return WBEM_E_INVALID_PARAMETER;
  436. *puKeyCount = m_Keys.Size();
  437. return S_OK;
  438. }
  439. /*++
  440. Routine Description:
  441. Sets the name/value pair for a key. If the key exists, then it is
  442. replace. If the name is empty, then all existing keys are deleted.
  443. Arguments:
  444. wszName - Key name. May be NULL
  445. uFlags - not used for now
  446. uCimType - data type
  447. pKeyVal - pointer to the data
  448. Return Value:
  449. S_OK if all is well, else an error code.
  450. --*/
  451. HRESULT CParsedComponent::SetKey(
  452. /* [string][in] */ LPCWSTR wszName,
  453. /* [in] */ ULONG uFlags,
  454. /* [in] */ ULONG uCimType,
  455. /* [in] */ LPVOID pKeyVal)
  456. {
  457. CSafeInCritSec cs(m_pCS->GetCS());
  458. if(!cs.IsOK())
  459. return WBEM_E_OUT_OF_MEMORY;
  460. DWORD dwCnt = 0;
  461. CKeyRef * pKey;
  462. m_bSingleton = false;
  463. DWORD dwSize = GetCIMSize(uCimType, pKeyVal);
  464. if(uFlags || pKeyVal == NULL || dwSize == 0)
  465. return WBEM_E_INVALID_PARAMETER;
  466. // If the current list has just a single unnamed entry, the delete it.
  467. if(m_Keys.Size() == 1)
  468. {
  469. pKey = (CKeyRef *)m_Keys[dwCnt];
  470. if(pKey->m_pName == NULL || pKey->m_pName[0] == 0)
  471. ClearKeys();
  472. }
  473. if(wszName == NULL || wcslen(wszName) < 1)
  474. {
  475. // If new key has null name, delete all existing entries.
  476. ClearKeys();
  477. }
  478. else
  479. {
  480. // If new key has name, look for current entry of same name
  481. for(dwCnt = 0; dwCnt < (DWORD)m_Keys.Size(); dwCnt++)
  482. {
  483. pKey = (CKeyRef *)m_Keys[dwCnt];
  484. if(pKey->m_pName && !_wcsicmp(pKey->m_pName, wszName))
  485. break;
  486. }
  487. }
  488. // If current entry of same name exists, replace it
  489. if(dwCnt < (DWORD)m_Keys.Size())
  490. {
  491. // If it exists, replace it
  492. pKey->SetData(uCimType, dwSize, pKeyVal);
  493. }
  494. else
  495. {
  496. // otherwise, new entry
  497. CKeyRef * pNew = new CKeyRef(wszName, uCimType, dwSize, pKeyVal);
  498. if(pNew)
  499. m_Keys.Add(pNew);
  500. else
  501. return WBEM_E_OUT_OF_MEMORY;
  502. }
  503. return S_OK;
  504. }
  505. /*++
  506. Routine Description:
  507. Converts a simple vartype to the cim equivalent
  508. Arguments:
  509. vt - simple vartype
  510. Return Value:
  511. valid cimtype. CIM_EMPTY is returned if there is an error.
  512. --*/
  513. DWORD CalcCimType(VARTYPE vt)
  514. {
  515. switch (vt)
  516. {
  517. case VT_I2:
  518. case VT_I4:
  519. case VT_R4:
  520. case VT_R8:
  521. case VT_BSTR:
  522. case VT_BOOL:
  523. case VT_UI1:
  524. return vt;
  525. default:
  526. return CIM_EMPTY;
  527. }
  528. }
  529. /*++
  530. Routine Description:
  531. Sets the name/value pair for a key. If the key exists, then it is
  532. replace. If the name is empty, then all existing keys are deleted.
  533. Arguments:
  534. wszName - Key name. May be NULL
  535. uFlags - not used for now
  536. uCimType - data type
  537. pKeyVal - pointer to the data
  538. Return Value:
  539. S_OK if all is well, else an error code.
  540. --*/
  541. HRESULT CParsedComponent::SetKey2(
  542. /* [string][in] */ LPCWSTR wszName,
  543. /* [in] */ ULONG uFlags,
  544. /* [in] */ ULONG uCimType,
  545. /* [in] */ VARIANT __RPC_FAR *pKeyVal)
  546. {
  547. CSafeInCritSec cs(m_pCS->GetCS());
  548. if(!cs.IsOK())
  549. return WBEM_E_OUT_OF_MEMORY;
  550. if(uFlags != 0 || pKeyVal == NULL || wszName == 0)
  551. return WBEM_E_INVALID_PARAMETER;
  552. // special code for the provider team
  553. if(uCimType == CIM_ILLEGAL)
  554. uCimType = CalcCimType(pKeyVal->vt);
  555. if(uCimType == CIM_EMPTY)
  556. return WBEM_E_INVALID_PARAMETER;
  557. if(uCimType == CIM_SINT64)
  558. {
  559. __int64 llVal = _wtoi64(pKeyVal->bstrVal);
  560. return SetKey(wszName, uFlags, CIM_SINT64, &llVal);
  561. }
  562. else if(uCimType == CIM_UINT64)
  563. {
  564. unsigned __int64 ullVal;
  565. char cTemp[50];
  566. wcstombs(cTemp, pKeyVal->bstrVal,50);
  567. if(sscanf(cTemp, "%I64u", &ullVal) != 1)
  568. return WBEM_E_INVALID_PARAMETER;
  569. return SetKey(wszName, uFlags, CIM_UINT64, &ullVal);
  570. }
  571. else if(pKeyVal->vt == VT_BSTR)
  572. {
  573. return SetKey(wszName, uFlags, uCimType, pKeyVal->bstrVal);
  574. }
  575. else
  576. {
  577. DWORD dwSize = GetCIMSize(uCimType, &pKeyVal->lVal);
  578. if(dwSize == 0)
  579. return WBEM_E_INVALID_PARAMETER;
  580. return SetKey(wszName, uFlags, uCimType, &pKeyVal->lVal);
  581. }
  582. }
  583. /*++
  584. Routine Description:
  585. Gets the key information based on the key's index. Note that all return
  586. values are optional.
  587. Arguments:
  588. uKeyIx - Zero based index of the desired key
  589. uNameBufSize - size of buffer in WCHAR of pszKeyName
  590. pszKeyName - where name is to be copied. Can be NULL if not needed
  591. uKeyValBufSize - size of pKeyVal buffer in bytes
  592. pKeyVal - where data is to be copied. Can be NULL if not needed
  593. puApparentCimType - data type. Can be NULL if not needed
  594. Return Value:
  595. S_OK if all is well, else an error code.
  596. --*/
  597. HRESULT CParsedComponent::GetKey(
  598. /* [in] */ ULONG uKeyIx,
  599. /* [in] */ ULONG uFlags,
  600. /* [out][in] */ ULONG __RPC_FAR *puNameBufSize,
  601. /* [out][in] */ LPWSTR pszKeyName,
  602. /* [out][in] */ ULONG __RPC_FAR *puKeyValBufSize,
  603. /* [in] */ LPVOID pKeyVal,
  604. /* [out] */ ULONG __RPC_FAR *puApparentCimType)
  605. {
  606. CSafeInCritSec cs(m_pCS->GetCS());
  607. if(!cs.IsOK())
  608. return WBEM_E_OUT_OF_MEMORY;
  609. bool bTooSmall = false;
  610. if(uKeyIx >= (DWORD)m_Keys.Size())
  611. return WBEM_E_INVALID_PARAMETER;
  612. if(uFlags != 0 && uFlags != WBEMPATH_TEXT && uFlags != WBEMPATH_QUOTEDTEXT)
  613. return WBEM_E_INVALID_PARAMETER;
  614. if(puNameBufSize && *puNameBufSize > 0 && pszKeyName == NULL)
  615. return WBEM_E_INVALID_PARAMETER;
  616. if(puKeyValBufSize && *puKeyValBufSize && pKeyVal == NULL)
  617. return WBEM_E_INVALID_PARAMETER;
  618. CKeyRef * pKey = (CKeyRef *)m_Keys[uKeyIx];
  619. if(puNameBufSize)
  620. {
  621. if(pKey->m_pName == NULL)
  622. {
  623. *puNameBufSize = 1;
  624. if(pszKeyName)
  625. pszKeyName[0] = 0;
  626. }
  627. else
  628. {
  629. DWORD dwSizeNeeded = wcslen(pKey->m_pName)+1;
  630. if(*puNameBufSize < dwSizeNeeded && pszKeyName)
  631. {
  632. bTooSmall = true;
  633. *puNameBufSize = dwSizeNeeded;
  634. }
  635. else
  636. {
  637. *puNameBufSize = dwSizeNeeded;
  638. if(pszKeyName)
  639. wcscpy(pszKeyName, pKey->m_pName);
  640. }
  641. }
  642. }
  643. if(puKeyValBufSize)
  644. {
  645. // get a pointer to the data and figure out how large it is
  646. DWORD dwSizeNeeded = 0;
  647. BYTE * pData = 0;
  648. bool bNeedToDelete = false;
  649. if(uFlags == 0)
  650. {
  651. dwSizeNeeded = pKey->m_dwSize;
  652. pData = (BYTE *)pKey->m_pData;
  653. }
  654. else
  655. {
  656. bool bQuoted = false;
  657. if(uFlags == WBEMPATH_QUOTEDTEXT)
  658. bQuoted = true;
  659. pData = (BYTE *)pKey->GetValue(bQuoted);
  660. if(pData == NULL)
  661. return WBEM_E_FAILED;
  662. bNeedToDelete = true;
  663. dwSizeNeeded = 2 * (wcslen((LPWSTR)pData)+1);
  664. }
  665. // Copy the data in
  666. if(*puKeyValBufSize < dwSizeNeeded && pKeyVal)
  667. {
  668. *puKeyValBufSize = dwSizeNeeded;
  669. if(bNeedToDelete)
  670. delete pData;
  671. return WBEM_E_BUFFER_TOO_SMALL;
  672. }
  673. *puKeyValBufSize = dwSizeNeeded;
  674. if(pData && pKeyVal)
  675. memcpy(pKeyVal, pData, dwSizeNeeded);
  676. if(bNeedToDelete)
  677. delete pData;
  678. }
  679. if(puApparentCimType)
  680. *puApparentCimType = pKey->m_dwType;
  681. if(bTooSmall)
  682. return WBEM_E_BUFFER_TOO_SMALL;
  683. else
  684. return S_OK;
  685. }
  686. /*++
  687. Routine Description:
  688. Gets the key information based on the key's index. Note that all return
  689. values are optional.
  690. Arguments:
  691. uKeyIx - Zero based index of the desired key
  692. uNameBufSize - size of buffer in WCHAR of pszKeyName
  693. pszKeyName - where name is to be copied. Can be NULL if not needed
  694. uKeyValBufSize - size of pKeyVal buffer in bytes
  695. pKeyVal - where data is to be copied. Can be NULL if not needed
  696. puApparentCimType - data type.
  697. Return Value:
  698. S_OK if all is well, else an error code.
  699. --*/
  700. HRESULT CParsedComponent::GetKey2(
  701. /* [in] */ ULONG uKeyIx,
  702. /* [in] */ ULONG uFlags,
  703. /* [out][in] */ ULONG __RPC_FAR *puNameBufSize,
  704. /* [out][in] */ LPWSTR pszKeyName,
  705. /* [out][in] */ VARIANT __RPC_FAR *pKeyValue,
  706. /* [out] */ ULONG __RPC_FAR *puApparentCimType)
  707. {
  708. DWORD dwSize = 50;
  709. WCHAR wTemp[50];
  710. CSafeInCritSec cs(m_pCS->GetCS());
  711. if(!cs.IsOK())
  712. return WBEM_E_OUT_OF_MEMORY;
  713. if(uKeyIx >= (DWORD)m_Keys.Size() || pKeyValue == NULL || puApparentCimType == NULL)
  714. return WBEM_E_INVALID_PARAMETER;
  715. CKeyRef * pKey = (CKeyRef *)m_Keys[uKeyIx];
  716. if(pKey->m_dwType == CIM_STRING || pKey->m_dwType == CIM_REFERENCE || pKey->m_dwType == CIM_DATETIME)
  717. dwSize = pKey->m_dwSize * 4 + 2;
  718. char * pTemp = new char[dwSize];
  719. if(pTemp == NULL)
  720. return WBEM_E_OUT_OF_MEMORY;
  721. CDeleteMe<char> dm(pTemp);
  722. HRESULT hr = GetKey(uKeyIx, uFlags, puNameBufSize,pszKeyName, &dwSize,
  723. (void *)pTemp, puApparentCimType);
  724. if(FAILED(hr))
  725. return hr;
  726. __int64 temp64;
  727. // convert to cim type;
  728. VariantClear(pKeyValue);
  729. switch (*puApparentCimType)
  730. {
  731. case CIM_STRING:
  732. case CIM_REFERENCE:
  733. case CIM_DATETIME:
  734. pKeyValue->vt = VT_BSTR;
  735. pKeyValue->bstrVal = SysAllocString((LPWSTR)pTemp);
  736. if(pKeyValue->bstrVal == NULL)
  737. return WBEM_E_OUT_OF_MEMORY;
  738. break;
  739. case CIM_UINT8:
  740. case CIM_SINT8:
  741. pKeyValue->vt = VT_UI1;
  742. memcpy((void*)&pKeyValue->lVal, pTemp, 1);
  743. break;
  744. case CIM_SINT16:
  745. case CIM_CHAR16:
  746. pKeyValue->vt = VT_I2;
  747. memcpy((void*)&pKeyValue->lVal, pTemp, 2);
  748. break;
  749. case CIM_UINT16:
  750. pKeyValue->vt = VT_I4;
  751. memcpy((void*)&pKeyValue->lVal, pTemp, 2);
  752. break;
  753. case CIM_SINT32:
  754. case CIM_UINT32:
  755. pKeyValue->vt = VT_I4;
  756. memcpy((void*)&pKeyValue->lVal, pTemp, 4);
  757. break;
  758. case CIM_BOOLEAN:
  759. pKeyValue->vt = VT_BOOL;
  760. memcpy((void*)&pKeyValue->lVal, pTemp, 4);
  761. break;
  762. case CIM_SINT64:
  763. case CIM_UINT64:
  764. memcpy((void *)&temp64, pTemp, 8);
  765. if(*puApparentCimType == CIM_SINT64)
  766. _i64tow(temp64, wTemp, 10);
  767. else
  768. _ui64tow(temp64, wTemp, 10);
  769. pKeyValue->vt = VT_BSTR;
  770. pKeyValue->bstrVal = SysAllocString(wTemp);
  771. if(pKeyValue->bstrVal == NULL)
  772. return WBEM_E_OUT_OF_MEMORY;
  773. break;
  774. }
  775. return hr;
  776. }
  777. /*++
  778. Routine Description:
  779. Removes a key from the key list.
  780. Arguments:
  781. wszName - Name of the key to be delete. Can be null if the key doesnt have a name.
  782. uFlags - not currently used.
  783. Return Value:
  784. S_OK if all is well, else an error code.
  785. --*/
  786. HRESULT CParsedComponent::RemoveKey(
  787. /* [string][in] */ LPCWSTR wszName,
  788. /* [in] */ ULONG uFlags)
  789. {
  790. CSafeInCritSec cs(m_pCS->GetCS());
  791. if(!cs.IsOK())
  792. return WBEM_E_OUT_OF_MEMORY;
  793. CKeyRef * pKey = NULL;
  794. bool bFound = false;
  795. DWORD dwCnt = 0;
  796. if(uFlags != 0)
  797. return WBEM_E_INVALID_PARAMETER;
  798. if(wszName == NULL || wszName[0] == 0)
  799. {
  800. // check for null key, it can match if single entry also null
  801. if(m_Keys.Size() == 1)
  802. {
  803. pKey = (CKeyRef *)m_Keys[dwCnt];
  804. if(pKey->m_pName == NULL || pKey->m_pName[0] == 0)
  805. bFound = true;
  806. }
  807. }
  808. else
  809. {
  810. // loop through and look for name match
  811. for(dwCnt = 0; dwCnt < (DWORD)m_Keys.Size(); dwCnt++)
  812. {
  813. pKey = (CKeyRef *)m_Keys[dwCnt];
  814. if(pKey->m_pName && !_wcsicmp(pKey->m_pName, wszName))
  815. {
  816. bFound = true;
  817. break;
  818. }
  819. }
  820. }
  821. if(bFound)
  822. {
  823. delete pKey;
  824. m_Keys.RemoveAt(dwCnt);
  825. return S_OK;
  826. }
  827. else
  828. return WBEM_E_INVALID_PARAMETER;
  829. }
  830. /*++
  831. Routine Description:
  832. Removes all keys from the key list.
  833. Arguments:
  834. wszName - Name of the key to be delete. Can be null if the key doesnt have a name.
  835. uFlags - not currently used.
  836. Return Value:
  837. S_OK if all is well, else an error code.
  838. --*/
  839. HRESULT CParsedComponent::RemoveAllKeys(
  840. /* [in] */ ULONG uFlags)
  841. {
  842. CSafeInCritSec cs(m_pCS->GetCS());
  843. if(!cs.IsOK())
  844. return WBEM_E_OUT_OF_MEMORY;
  845. if(uFlags != 0)
  846. return WBEM_E_INVALID_PARAMETER;
  847. ClearKeys();
  848. return S_OK;
  849. }
  850. /*++
  851. Routine Description:
  852. Sets or unsets a key to be singleton.
  853. Arguments:
  854. bSet - if true, then all keys are deleted and the singleton flag is set.
  855. if false, then the singleton flag is cleared.
  856. Return Value:
  857. S_OK if all is well, else an error code.
  858. --*/
  859. HRESULT CParsedComponent::MakeSingleton(boolean bSet)
  860. {
  861. CSafeInCritSec cs(m_pCS->GetCS());
  862. if(!cs.IsOK())
  863. return WBEM_E_OUT_OF_MEMORY;
  864. if(bSet)
  865. {
  866. ClearKeys();
  867. m_bSingleton = true;
  868. }
  869. else
  870. m_bSingleton = false;
  871. return S_OK;
  872. }
  873. /*++
  874. Routine Description:
  875. Returns information about a particular key list.
  876. Arguments:
  877. uRequestedInfo - Not currently used, should be set to zero
  878. puResponse - any appropriate values will be OR'ed into this
  879. Return Value:
  880. S_OK if all is well, else an error code.
  881. --*/
  882. HRESULT CParsedComponent::GetInfo(
  883. /* [in] */ ULONG uRequestedInfo,
  884. /* [out] */ ULONGLONG __RPC_FAR *puResponse)
  885. {
  886. CSafeInCritSec cs(m_pCS->GetCS());
  887. if(!cs.IsOK())
  888. return WBEM_E_OUT_OF_MEMORY;
  889. if(uRequestedInfo != 0 || puResponse == NULL)
  890. return WBEM_E_INVALID_PARAMETER;
  891. *puResponse = 0;
  892. ULONG ulKeyCnt = m_Keys.Size();
  893. if(ulKeyCnt > 1)
  894. *puResponse |= WBEMPATH_INFO_IS_COMPOUND;
  895. for(DWORD dwKey = 0; dwKey < ulKeyCnt; dwKey++)
  896. {
  897. CKeyRef * pKey = (CKeyRef *)m_Keys[dwKey];
  898. if(pKey->m_pName == NULL || wcslen(pKey->m_pName) < 1)
  899. *puResponse |= WBEMPATH_INFO_HAS_IMPLIED_KEY;
  900. if(pKey->m_dwType == CIM_REFERENCE)
  901. *puResponse |= WBEMPATH_INFO_HAS_V2_REF_PATHS;
  902. }
  903. if(m_bSingleton)
  904. *puResponse |= WBEMPATH_INFO_CONTAINS_SINGLETON;
  905. return S_OK;
  906. }
  907. /*++
  908. Routine Description:
  909. Returns text version of a particular key list.
  910. Arguments:
  911. lFlags - 0 is only current value
  912. uBuffLength - number of WCHAR which can fit into pszText
  913. pszText - buffer supplied by caller where data is to be copied
  914. Return Value:
  915. S_OK if all is well, else an error code.
  916. --*/
  917. HRESULT CParsedComponent::GetText(
  918. /* [in] */ long lFlags,
  919. /* [out][in] */ ULONG __RPC_FAR *puBuffLength,
  920. /* [string][out] */ LPWSTR pszText)
  921. {
  922. CSafeInCritSec cs(m_pCS->GetCS());
  923. if(!cs.IsOK())
  924. return WBEM_E_OUT_OF_MEMORY;
  925. if((lFlags != 0 && lFlags != WBEMPATH_QUOTEDTEXT && lFlags != WBEMPATH_TEXT) || puBuffLength == NULL)
  926. return WBEM_E_INVALID_PARAMETER;
  927. BSTR data = NULL;
  928. bool bGetQuotes = false;
  929. if(lFlags & WBEMPATH_QUOTEDTEXT)
  930. bGetQuotes = true;
  931. HRESULT hr = Unparse(&data, bGetQuotes, false);
  932. if(FAILED(hr))
  933. return hr;
  934. if(data == NULL)
  935. return WBEM_E_FAILED;
  936. DWORD dwBuffSize = *puBuffLength;
  937. DWORD dwSizeNeeded = wcslen(data)+1;
  938. *puBuffLength = dwSizeNeeded;
  939. hr = S_OK;
  940. if(pszText)
  941. {
  942. if(dwSizeNeeded > dwBuffSize)
  943. hr = WBEM_E_BUFFER_TOO_SMALL;
  944. else
  945. wcscpy(pszText, data);
  946. }
  947. SysFreeString(data);
  948. return hr;
  949. }
  950. /*++
  951. Routine Description:
  952. Cleans out a key list.
  953. --*/
  954. void CParsedComponent::ClearKeys ()
  955. {
  956. DWORD dwSize = m_Keys.Size();
  957. for ( ULONG dwDeleteIndex = 0 ; dwDeleteIndex < dwSize ;
  958. dwDeleteIndex ++ )
  959. {
  960. CKeyRef * pDel = (CKeyRef *)m_Keys[dwDeleteIndex];
  961. delete pDel;
  962. }
  963. m_Keys.Empty();
  964. }
  965. /*++
  966. Routine Description:
  967. Determines if the key list could be for an instance.
  968. Return Value:
  969. true if path has keys or is marked as singleton.
  970. --*/
  971. bool CParsedComponent::IsInstance()
  972. {
  973. if(m_bSingleton || m_Keys.Size())
  974. return true;
  975. else
  976. return false;
  977. }
  978. /*++
  979. Routine Description:
  980. Adds a key to the key list.
  981. Arguments:
  982. CKeyRef - key to be added. Note that it is now owned by the key list
  983. and should not be freed by the caller.
  984. Return Value:
  985. TRUE if all is well.
  986. --*/
  987. BOOL CParsedComponent::AddKeyRef(CKeyRef* pAcquireRef)
  988. {
  989. if(pAcquireRef == NULL)
  990. return FALSE;
  991. if(CFlexArray::no_error == m_Keys.Add(pAcquireRef))
  992. return TRUE;
  993. else
  994. return FALSE;
  995. }
  996. /*++
  997. Routine Description:
  998. Tests a component to determine if it could be a namespace. That is true
  999. only if it contains a single string value with no class name or key name.
  1000. Return Value:
  1001. TRUE if it could be a namespace.
  1002. --*/
  1003. bool CParsedComponent::IsPossibleNamespace()
  1004. {
  1005. if(m_sClassName && wcslen(m_sClassName))
  1006. return false;
  1007. if(m_Keys.Size() != 1)
  1008. return false;
  1009. CKeyRef * pKey = (CKeyRef *)m_Keys[0];
  1010. if(pKey->m_pName && wcslen(pKey->m_pName))
  1011. return false;
  1012. if(pKey->m_dwType != CIM_STRING)
  1013. return false;
  1014. if(pKey->m_pData == NULL)
  1015. return false;
  1016. else
  1017. return true;
  1018. }
  1019. /*++
  1020. Routine Description:
  1021. Sets a component to be a namespace.
  1022. Arguments:
  1023. pName - Name to be added.
  1024. Return Value:
  1025. S_OK if all is well, else standard error code.
  1026. --*/
  1027. HRESULT CParsedComponent::SetNS(LPCWSTR pName)
  1028. {
  1029. if(pName == NULL)
  1030. return WBEM_E_INVALID_PARAMETER;
  1031. CKeyRef * pNew = new CKeyRef;
  1032. if(pNew == NULL)
  1033. return WBEM_E_OUT_OF_MEMORY;
  1034. DWORD dwStrSize = wcslen(pName) + 1; // one for the numm
  1035. pNew->m_dwSize = 2 * dwStrSize; // size is in byte, not unicode
  1036. pNew->m_pData = new WCHAR[dwStrSize];
  1037. if(pNew->m_pData == NULL)
  1038. {
  1039. delete pNew;
  1040. return WBEM_E_OUT_OF_MEMORY;
  1041. }
  1042. wcscpy((LPWSTR)pNew->m_pData, pName);
  1043. pNew->m_dwType = CIM_STRING;
  1044. if(CFlexArray::no_error == m_Keys.Add(pNew))
  1045. return S_OK;
  1046. else
  1047. {
  1048. delete pNew;
  1049. return WBEM_E_OUT_OF_MEMORY;
  1050. }
  1051. }
  1052. //***************************************************************************
  1053. //
  1054. // CDefPathParser
  1055. //
  1056. //***************************************************************************
  1057. /*++
  1058. Routine Description:
  1059. Constructor.
  1060. --*/
  1061. CDefPathParser::CDefPathParser(void)
  1062. {
  1063. m_cRef=1;
  1064. m_pServer = 0; // NULL if no server
  1065. m_dwStatus = OK;
  1066. m_bParent = false;
  1067. m_pRawPath = NULL;
  1068. m_wszOriginalPath = NULL;
  1069. m_bSetViaUMIPath = false;
  1070. m_pCS = new CRefCntCS;
  1071. if(m_pCS == NULL || FAILED(m_pCS->GetStatus()))
  1072. m_dwStatus = FAILED_TO_INIT;
  1073. InterlockedIncrement(&g_cObj);
  1074. m_bServerNameSetByDefault = false;
  1075. m_pFTM = NULL;
  1076. CoCreateFreeThreadedMarshaler((IWbemPath*)this, &m_pFTM);
  1077. m_pGenLex = NULL;
  1078. m_dwException = 0;
  1079. return;
  1080. };
  1081. /*++
  1082. Routine Description:
  1083. Destructor.
  1084. --*/
  1085. CDefPathParser::~CDefPathParser(void)
  1086. {
  1087. if(m_pCS)
  1088. m_pCS->Release();
  1089. Empty();
  1090. m_pCS = NULL;
  1091. InterlockedDecrement(&g_cObj);
  1092. if(m_pFTM)
  1093. m_pFTM->Release();
  1094. return;
  1095. }
  1096. /*++
  1097. Routine Description:
  1098. Gets the total number of namespaces, scopes, and class parts.
  1099. Return Value:
  1100. Number of components.
  1101. --*/
  1102. DWORD CDefPathParser::GetNumComponents()
  1103. {
  1104. int iSize = m_Components.Size();
  1105. return iSize;
  1106. }
  1107. /*++
  1108. Routine Description:
  1109. Determines if there is anything in the path.
  1110. Return Value:
  1111. true if there is no server, namepace, scope or class part.
  1112. --*/
  1113. bool CDefPathParser::IsEmpty()
  1114. {
  1115. if(m_pServer || GetNumComponents() || m_pRawPath)
  1116. return false;
  1117. else
  1118. return true;
  1119. }
  1120. /*++
  1121. Routine Description:
  1122. Cleans out the data. Used by destructor.
  1123. --*/
  1124. void CDefPathParser::Empty(void)
  1125. {
  1126. m_bSetViaUMIPath = false;
  1127. delete m_pServer;
  1128. m_bParent = false;
  1129. m_pServer = NULL;
  1130. delete m_pRawPath;
  1131. m_pRawPath = NULL;
  1132. delete m_wszOriginalPath;
  1133. m_wszOriginalPath = NULL;
  1134. for (DWORD dwIx = 0; dwIx < (DWORD)m_Components.Size(); dwIx++)
  1135. {
  1136. CParsedComponent * pCom = (CParsedComponent *)m_Components[dwIx];
  1137. pCom->Release();
  1138. }
  1139. m_Components.Empty();
  1140. return;
  1141. }
  1142. /*++
  1143. Routine Description:
  1144. Gets the component string. The string varies depending on if the component
  1145. if a namepace, or scope or path.
  1146. Arguments:
  1147. i - zero based index
  1148. pUnparsed - where the string is returned. The caller must free via SysFreeString.
  1149. wDelim - Delimiter for this type
  1150. Return Value:
  1151. S_OK if all is well, else an error code.
  1152. --*/
  1153. HRESULT CDefPathParser::GetComponentString(ULONG i, BSTR * pUnparsed, WCHAR & wDelim)
  1154. {
  1155. DWORD dwNs = GetNumNamespaces();
  1156. DWORD dwSc = m_Components.Size();
  1157. if(i < dwNs)
  1158. {
  1159. CParsedComponent * pNS = (CParsedComponent *)m_Components[i];
  1160. wDelim = L'\\';
  1161. return pNS->Unparse(pUnparsed, false, true);
  1162. }
  1163. CParsedComponent * pInst = NULL;
  1164. if(i < (dwSc))
  1165. pInst = (CParsedComponent *)m_Components[i];
  1166. if(pInst == NULL)
  1167. return WBEM_E_INVALID_PARAMETER;
  1168. wDelim = L':';
  1169. HRESULT hRes;
  1170. hRes = pInst->Unparse(pUnparsed, true, true);
  1171. return hRes;
  1172. }
  1173. /*++
  1174. Routine Description:
  1175. Returns the path
  1176. Arguments:
  1177. nStartAt - first component to be added to the path
  1178. nStopAt - last component to be added to the path. Note that this is usually just set to
  1179. the number of components.
  1180. Return Value:
  1181. pointer to the string. The caller must free this via delete. If there is an Error, NULL is returned.
  1182. --*/
  1183. LPWSTR CDefPathParser::GetPath(DWORD nStartAt, DWORD nStopAt,bool bGetServer)
  1184. {
  1185. DWORD dwSize = 1024, dwUsed = 0;
  1186. if(bGetServer && m_pServer && wcslen(m_pServer) > 1000)
  1187. dwSize = 2 * wcslen(m_pServer);
  1188. LPWSTR wszOut = new WCHAR[dwSize];
  1189. if(wszOut == NULL)
  1190. return NULL;
  1191. wszOut[0] = 0;
  1192. bool bFirst = true;
  1193. if(bGetServer && m_pServer && wcslen(m_pServer) < 1020)
  1194. {
  1195. int iLen = wcslen(m_pServer) + 3; // allow for back slashes
  1196. wcscpy(wszOut, L"\\\\");
  1197. wcscat(wszOut, m_pServer);
  1198. wcscat(wszOut, L"\\");
  1199. dwUsed = iLen;
  1200. }
  1201. for (unsigned int i = nStartAt; (int)i < (int)nStopAt; i++)
  1202. {
  1203. BSTR sTemp = NULL;
  1204. WCHAR wDel;
  1205. HRESULT hRes = GetComponentString(i, &sTemp, wDel);
  1206. if(FAILED(hRes))
  1207. {
  1208. delete wszOut;
  1209. return NULL;
  1210. }
  1211. CSysFreeMe fm(sTemp);
  1212. int iLen = wcslen(sTemp);
  1213. if ((iLen + dwUsed) > dwSize)
  1214. {
  1215. DWORD dwNewSize = 2*(dwSize + iLen);
  1216. LPWSTR lpTemp = new WCHAR[dwNewSize];
  1217. CDeleteMe<WCHAR> dm(wszOut);
  1218. if(lpTemp == NULL)
  1219. return NULL;
  1220. memcpy(lpTemp,wszOut, dwSize * sizeof(WCHAR));
  1221. dwSize = dwNewSize;
  1222. wszOut = lpTemp;
  1223. }
  1224. if (!bFirst)
  1225. {
  1226. int n = wcslen(wszOut);
  1227. wszOut[n] = wDel;
  1228. wszOut[n+1] = '\0';
  1229. iLen++;
  1230. }
  1231. bFirst = false;
  1232. wcscat(wszOut, sTemp);
  1233. dwUsed += iLen;
  1234. }
  1235. return wszOut;
  1236. }
  1237. /*++
  1238. Routine Description:
  1239. Adds a namespace.
  1240. Arguments:
  1241. wszNamespace - Name to be set into the namespace.
  1242. Return Value:
  1243. TRUE if all is well.
  1244. --*/
  1245. BOOL CDefPathParser::AddNamespace(LPCWSTR wszNamespace)
  1246. {
  1247. BOOL bRet = FALSE;
  1248. DWORD dwNumNS = GetNumNamespaces();
  1249. CParsedComponent *pNew = new CParsedComponent(m_pCS);
  1250. if (pNew)
  1251. {
  1252. HRESULT hr = pNew->SetNS(wszNamespace);
  1253. if(FAILED(hr))
  1254. {
  1255. delete pNew;
  1256. return FALSE;
  1257. }
  1258. int iRet = m_Components.InsertAt(dwNumNS, pNew);
  1259. if(iRet != CFlexArray::no_error)
  1260. {
  1261. delete pNew;
  1262. bRet = FALSE;
  1263. }
  1264. else
  1265. bRet = TRUE;
  1266. }
  1267. return bRet;
  1268. }
  1269. /*++
  1270. Routine Description:
  1271. This is used during the parsing of the path and is
  1272. just a convenient way to get at the last scope. Note
  1273. that during this phase, the class part is in the scope
  1274. list.
  1275. Return Value:
  1276. pointer to last scope or NULL if there isnt one.
  1277. --*/
  1278. CParsedComponent * CDefPathParser::GetLastComponent()
  1279. {
  1280. DWORD dwSize = m_Components.Size();
  1281. if (dwSize > (DWORD)GetNumNamespaces())
  1282. return (CParsedComponent *)m_Components[dwSize-1];
  1283. else
  1284. return NULL;
  1285. }
  1286. /*++
  1287. Routine Description:
  1288. Adds new class. This is used during the parsing stage when
  1289. the class is just treated as the last scope.
  1290. Arguments:
  1291. lpClassName - Name of the class
  1292. Return Value:
  1293. TRUE if ok
  1294. --*/
  1295. BOOL CDefPathParser::AddClass(LPCWSTR lpClassName)
  1296. {
  1297. BOOL bRet = FALSE;
  1298. CParsedComponent *pNew = new CParsedComponent(m_pCS);
  1299. if (pNew)
  1300. {
  1301. pNew->m_sClassName = SysAllocString(lpClassName);
  1302. if(pNew->m_sClassName)
  1303. {
  1304. m_Components.Add(pNew);
  1305. bRet = TRUE;
  1306. }
  1307. else
  1308. delete pNew;
  1309. }
  1310. return bRet;
  1311. }
  1312. /*++
  1313. Routine Description:
  1314. Adds a key/value pair.
  1315. Arguments:
  1316. pKey - Data to be added. Note that this is acquired by this routine.
  1317. Return Value:
  1318. TRUE if all is well
  1319. --*/
  1320. BOOL CDefPathParser::AddKeyRef(CKeyRef *pRef)
  1321. {
  1322. BOOL bRet = FALSE;
  1323. CParsedComponent *pTemp = GetLastComponent();
  1324. if (pTemp)
  1325. {
  1326. DWORD dwType = 0;
  1327. bRet = pTemp->AddKeyRef(pRef);
  1328. }
  1329. return bRet;
  1330. }
  1331. /*++
  1332. Routine Description:
  1333. Sets the most recent class to be singleton.
  1334. Return Value:
  1335. TRUE if OK.
  1336. --*/
  1337. BOOL CDefPathParser::SetSingletonObj()
  1338. {
  1339. BOOL bRet = FALSE;
  1340. CParsedComponent *pTemp = GetLastComponent();
  1341. if (pTemp)
  1342. pTemp->MakeSingleton(true);
  1343. return bRet;
  1344. }
  1345. /*++
  1346. Routine Description:
  1347. Sets the path text. This causes object to be emptied, the path to be parsed
  1348. and the object be rebuilt.
  1349. Arguments:
  1350. uMode - mode, can be
  1351. WBEMPATH_CREATE_ACCEPT_RELATIVE
  1352. WBEMPATH_CREATE_ACCEPT_ABSOLUTE
  1353. WBEMPATH_CREATE_ACCEPT_ALL
  1354. pszPath - Path.
  1355. Return Value:
  1356. S_OK if all is well, else an error code.
  1357. --*/
  1358. HRESULT CDefPathParser::SetText(
  1359. /* [in] */ ULONG uMode,
  1360. /* [in] */ LPCWSTR pszPath)
  1361. {
  1362. CSafeInCritSec cs(m_pCS->GetCS());
  1363. if(!cs.IsOK())
  1364. return WBEM_E_OUT_OF_MEMORY;
  1365. if(pszPath == NULL)
  1366. return WBEM_E_INVALID_PARAMETER;
  1367. if(!IsEmpty())
  1368. Empty();
  1369. if ((uMode & WBEMPATH_CREATE_ACCEPT_ALL) != 0 && wcslen (pszPath) == 0)
  1370. return S_OK;
  1371. try
  1372. {
  1373. m_wszOriginalPath = new WCHAR[wcslen(pszPath)+1];
  1374. if(m_wszOriginalPath)
  1375. {
  1376. wcscpy(m_wszOriginalPath, pszPath);
  1377. if(wcscmp(pszPath, L"..") == 0)
  1378. {
  1379. m_bParent = true;
  1380. m_dwStatus = OK;
  1381. return S_OK;
  1382. }
  1383. // if a umi path is being passed in, use that parser for it
  1384. if(Equal(pszPath, L"UMI:", 4))
  1385. {
  1386. return Set(uMode, pszPath);
  1387. }
  1388. else if(Equal(pszPath, L"UMILDAP:", 8) || Equal(pszPath, L"UMIWINNT:", 9))
  1389. {
  1390. return Set(0x8000, pszPath);
  1391. }
  1392. // normal case
  1393. CActualPathParser parser(uMode);
  1394. int iRet = parser.Parse(pszPath, *this);
  1395. if(iRet == 0)
  1396. {
  1397. m_dwStatus = OK;
  1398. return S_OK;
  1399. }
  1400. else
  1401. {
  1402. m_dwStatus = BAD_STRING;
  1403. return WBEM_E_INVALID_PARAMETER;
  1404. }
  1405. }
  1406. else
  1407. {
  1408. return WBEM_E_OUT_OF_MEMORY;
  1409. }
  1410. }
  1411. catch(...)
  1412. {
  1413. m_dwStatus = EXECEPTION_THROWN;
  1414. return WBEM_E_CRITICAL_ERROR;
  1415. }
  1416. }
  1417. /*++
  1418. Routine Description:
  1419. Create a WMI path from the object
  1420. Arguments:
  1421. lFlags - 0
  1422. uBuffLength - number of WCHAR which can fit into pszText
  1423. pszText - buffer supplied by caller where data is to be copied
  1424. Return Value:
  1425. S_OK if all is well, else an error code.
  1426. --*/
  1427. HRESULT CDefPathParser::GetText(
  1428. /* [in] */ long lFlags,
  1429. /* [in] */ ULONG * puBuffLength,
  1430. /* [string][out] */ LPWSTR pszText)
  1431. {
  1432. CSafeInCritSec cs(m_pCS->GetCS());
  1433. if(!cs.IsOK())
  1434. return WBEM_E_OUT_OF_MEMORY;
  1435. if(puBuffLength == NULL || (*puBuffLength > 0 &&pszText == NULL))
  1436. return WBEM_E_INVALID_PARAMETER;
  1437. if(lFlags != 0 && lFlags != WBEMPATH_GET_RELATIVE_ONLY && lFlags != WBEMPATH_GET_SERVER_TOO &&
  1438. lFlags != WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY && lFlags != WBEMPATH_GET_NAMESPACE_ONLY &&
  1439. lFlags != WBEMPATH_GET_ORIGINAL)
  1440. return WBEM_E_INVALID_PARAMETER;
  1441. if(lFlags == WBEMPATH_GET_ORIGINAL && m_wszOriginalPath)
  1442. {
  1443. DWORD dwSizeNeeded = wcslen(m_wszOriginalPath) + 1;
  1444. DWORD dwBuffSize = *puBuffLength;
  1445. *puBuffLength = dwSizeNeeded;
  1446. if(pszText)
  1447. {
  1448. if(dwSizeNeeded > dwBuffSize)
  1449. return WBEM_E_BUFFER_TOO_SMALL;
  1450. wcscpy(pszText, m_wszOriginalPath);
  1451. }
  1452. return S_OK;
  1453. }
  1454. LPWSTR pTemp = NULL;
  1455. DWORD dwStartAt = 0;
  1456. if(lFlags & WBEMPATH_GET_RELATIVE_ONLY)
  1457. dwStartAt = GetNumNamespaces();
  1458. bool bGetServer = false;
  1459. if(lFlags & WBEMPATH_GET_SERVER_TOO || lFlags & WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY)
  1460. bGetServer = true;
  1461. DWORD dwNum;
  1462. if(lFlags & WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY ||
  1463. lFlags & WBEMPATH_GET_NAMESPACE_ONLY)
  1464. dwNum = GetNumNamespaces();
  1465. else
  1466. dwNum = GetNumComponents();
  1467. // If just a relative path is specified, then dont prepend the server since that
  1468. // will create an invalid path
  1469. if(bGetServer && GetNumNamespaces() == 0 && m_bServerNameSetByDefault == true)
  1470. bGetServer = false;
  1471. pTemp = GetPath(dwStartAt, dwNum, bGetServer);
  1472. if(pTemp == NULL)
  1473. return WBEM_E_FAILED;
  1474. CDeleteMe<WCHAR> dm(pTemp);
  1475. DWORD dwSizeNeeded = wcslen(pTemp) + 1;
  1476. DWORD dwBuffSize = *puBuffLength;
  1477. *puBuffLength = dwSizeNeeded;
  1478. if(pszText)
  1479. {
  1480. if(dwSizeNeeded > dwBuffSize)
  1481. return WBEM_E_BUFFER_TOO_SMALL;
  1482. wcscpy(pszText, pTemp);
  1483. }
  1484. return S_OK;
  1485. }
  1486. CParsedComponent * CDefPathParser::GetClass()
  1487. {
  1488. DWORD dwNS = GetNumNamespaces();
  1489. DWORD dwScopes = m_Components.Size() - dwNS;
  1490. if(dwScopes < 1)
  1491. return NULL;
  1492. int iLast = m_Components.Size()-1;
  1493. return (CParsedComponent *)m_Components.GetAt(iLast);
  1494. }
  1495. /*++
  1496. Routine Description:
  1497. Gets information about the object path.
  1498. Arguments:
  1499. uRequestedInfo - Must be zero for now
  1500. puResponse - The various flags in tag_WMI_PATH_STATUS_FLAG are
  1501. OR'ed in as appropriate.
  1502. Return Value:
  1503. S_OK if all is well, else an error code.
  1504. --*/
  1505. HRESULT CDefPathParser::GetInfo(/* [in] */ ULONG uRequestedInfo,
  1506. /* [out] */ ULONGLONG __RPC_FAR *puResponse)
  1507. {
  1508. CSafeInCritSec cs(m_pCS->GetCS());
  1509. if(!cs.IsOK())
  1510. return WBEM_E_OUT_OF_MEMORY;
  1511. if(uRequestedInfo != 0 || puResponse == NULL)
  1512. return WBEM_E_INVALID_PARAMETER;
  1513. *puResponse = 0;
  1514. // special case for ".." paths.
  1515. if(IsEmpty() && m_bParent)
  1516. {
  1517. *puResponse |= WBEMPATH_INFO_IS_PARENT;
  1518. return S_OK;
  1519. }
  1520. // bits for
  1521. // WBEMPATH_INFO_NATIVE_PATH = 0X8000,
  1522. // WBEMPATH_INFO_WMI_PATH = 0X10000,
  1523. if(m_bSetViaUMIPath)
  1524. *puResponse |= WBEMPATH_INFO_WMI_PATH;
  1525. if(m_pRawPath)
  1526. *puResponse |= WBEMPATH_INFO_NATIVE_PATH;
  1527. // Bits for
  1528. // WBEMPATH_INFO_ANON_LOCAL_MACHINE <path has \\. as server name>
  1529. // WBEMPATH_INFO_HAS_MACHINE_NAME <not a dot>
  1530. // WBEMPATH_INFO_PATH_HAD_SERVER <there is a path and it was not specified by default>
  1531. if(m_pServer == NULL || !_wcsicmp(m_pServer, L"."))
  1532. *puResponse |= WBEMPATH_INFO_ANON_LOCAL_MACHINE;
  1533. else
  1534. *puResponse |= WBEMPATH_INFO_HAS_MACHINE_NAME;
  1535. if(m_pServer && m_bServerNameSetByDefault == false)
  1536. *puResponse |= WBEMPATH_INFO_PATH_HAD_SERVER;
  1537. // WBEMPATH_INFO_HAS_SUBSCOPES <true if a subscope is present
  1538. DWORD dwNS = GetNumNamespaces();
  1539. DWORD dwScopes = m_Components.Size() - dwNS;
  1540. if(dwScopes)
  1541. *puResponse |= WBEMPATH_INFO_HAS_SUBSCOPES;
  1542. // Bits for
  1543. // WBEMPATH_INFO_IS_CLASS_REF <a path to a classs, not a path to an instance
  1544. // WBEMPATH_INFO_IS_INST_REF <a path to an instance
  1545. CParsedComponent * pClass = GetClass();
  1546. if (pClass)
  1547. {
  1548. DWORD dwType = 0;
  1549. if(pClass->IsInstance())
  1550. *puResponse |= WBEMPATH_INFO_IS_INST_REF;
  1551. else
  1552. *puResponse |= WBEMPATH_INFO_IS_CLASS_REF;
  1553. if(pClass->m_bSingleton)
  1554. *puResponse |= WBEMPATH_INFO_IS_SINGLETON;
  1555. }
  1556. else
  1557. if(dwScopes == 0)
  1558. *puResponse |= WBEMPATH_INFO_SERVER_NAMESPACE_ONLY;
  1559. // loop through all the scopes and the class deff.
  1560. // set the following
  1561. // WBEMPATH_INFO_IS_COMPOUND <true if compound key is used
  1562. // WBEMPATH_INFO_HAS_V2_REF_PATHS <true if V2-style ref paths are used
  1563. // WBEMPATH_INFO_HAS_IMPLIED_KEY <true if keynames are missing somewhere
  1564. // WBEMPATH_INFO_CONTAINS_SINGLETON <true if one or more singletons
  1565. unsigned __int64 llRet = 0;
  1566. for (unsigned int iCnt = dwNS; iCnt < (DWORD)m_Components.Size(); iCnt++)
  1567. {
  1568. CParsedComponent *pComp = (CParsedComponent *)m_Components[iCnt];
  1569. pComp->GetInfo(0, &llRet);
  1570. *puResponse |= llRet;
  1571. }
  1572. if(pClass)
  1573. {
  1574. pClass->GetInfo(0, &llRet);
  1575. *puResponse |= llRet;
  1576. }
  1577. // For now, assume that v1 compilance means no scopes or new references
  1578. bool bOK = (!IsEmpty() && m_dwStatus == OK);
  1579. if(dwScopes == 0 && (*puResponse & WBEMPATH_INFO_HAS_V2_REF_PATHS) == 0 && bOK)
  1580. *puResponse |= WBEMPATH_INFO_V1_COMPLIANT;
  1581. // WBEMPATH_INFO_V2_COMPLIANT <true if path is WMI-V2-compliant
  1582. // WBEMPATH_INFO_CIM_COMPLIANT <true if path is CIM-compliant
  1583. if(bOK)
  1584. {
  1585. // todo, need to define cim compliance
  1586. *puResponse |= WBEMPATH_INFO_V2_COMPLIANT;
  1587. *puResponse |= WBEMPATH_INFO_CIM_COMPLIANT;
  1588. }
  1589. return S_OK;
  1590. }
  1591. /*++
  1592. Routine Description:
  1593. Sets the server portion of the path.
  1594. Arguments:
  1595. Name - New server name.
  1596. Return Value:
  1597. S_OK if all is well, else an error code.
  1598. --*/
  1599. HRESULT CDefPathParser::SetServer(
  1600. /* [string][in] */ LPCWSTR Name)
  1601. {
  1602. return SetServer(Name, false, false);
  1603. }
  1604. HRESULT CDefPathParser::SetServer(
  1605. /* [string][in] */ LPCWSTR Name, bool bServerNameSetByDefault, bool bAcquire)
  1606. {
  1607. m_bServerNameSetByDefault = bServerNameSetByDefault;
  1608. CSafeInCritSec cs(m_pCS->GetCS());
  1609. if(!cs.IsOK())
  1610. return WBEM_E_OUT_OF_MEMORY;
  1611. delete m_pServer;
  1612. m_pServer = NULL;
  1613. if(Name == NULL) // it is ok to have a null server an
  1614. return S_OK;
  1615. if(bAcquire)
  1616. {
  1617. m_pServer = (LPWSTR)Name;
  1618. }
  1619. else
  1620. {
  1621. m_pServer = new WCHAR[wcslen(Name)+1];
  1622. if(m_pServer == NULL)
  1623. return WBEM_E_OUT_OF_MEMORY;
  1624. wcscpy(m_pServer, Name);
  1625. }
  1626. return S_OK;
  1627. }
  1628. /*++
  1629. Routine Description:
  1630. Gets the server portion of the path
  1631. Arguments:
  1632. puNameBufLength - size of pName in WCHAR. On return, set to size used or needed
  1633. pName - caller allocated buffer where date is to be copied
  1634. Return Value:
  1635. S_OK if all is well, else an error code.
  1636. --*/
  1637. HRESULT CDefPathParser::GetServer(
  1638. /* [out][in] */ ULONG __RPC_FAR *puNameBufLength,
  1639. /* [string][out] */ LPWSTR pName)
  1640. {
  1641. CSafeInCritSec cs(m_pCS->GetCS());
  1642. if(!cs.IsOK())
  1643. return WBEM_E_OUT_OF_MEMORY;
  1644. if(puNameBufLength == 0 || (*puNameBufLength > 0 && pName == NULL))
  1645. return WBEM_E_INVALID_PARAMETER;
  1646. if(m_pServer == NULL)
  1647. return WBEM_E_NOT_AVAILABLE;
  1648. DWORD dwSizeNeeded = wcslen(m_pServer)+1;
  1649. DWORD dwBuffSize = *puNameBufLength;
  1650. *puNameBufLength = dwSizeNeeded;
  1651. if(pName)
  1652. {
  1653. if(dwSizeNeeded > dwBuffSize)
  1654. return WBEM_E_BUFFER_TOO_SMALL;
  1655. wcscpy(pName, m_pServer);
  1656. }
  1657. return S_OK;
  1658. }
  1659. /*++
  1660. Routine Description:
  1661. Gets the number of namespaces
  1662. Arguments:
  1663. puCount - Set to the number of namespaces.
  1664. Return Value:
  1665. S_OK if all is well, else an error code.
  1666. --*/
  1667. HRESULT CDefPathParser::GetNamespaceCount(
  1668. /* [out] */ ULONG __RPC_FAR *puCount)
  1669. {
  1670. CSafeInCritSec cs(m_pCS->GetCS());
  1671. if(!cs.IsOK())
  1672. return WBEM_E_OUT_OF_MEMORY;
  1673. if(puCount == NULL)
  1674. return WBEM_E_INVALID_PARAMETER;
  1675. *puCount = GetNumNamespaces();
  1676. return S_OK;
  1677. }
  1678. /*++
  1679. Routine Description:
  1680. Inserts a namespace into the path. An index of 0 inserts it
  1681. at the front of the list. The maximum allowed value is equal
  1682. to the current number of namespaces which results in adding it
  1683. to the end of the list.
  1684. Arguments:
  1685. uIndex - See above
  1686. pszName - Name of the new Namespace
  1687. Return Value:
  1688. S_OK if all is well, else an error code.
  1689. --*/
  1690. HRESULT CDefPathParser::SetNamespaceAt(/* [in] */ ULONG uIndex,
  1691. /* [string][in] */ LPCWSTR pszName)
  1692. {
  1693. CSafeInCritSec cs(m_pCS->GetCS());
  1694. if(!cs.IsOK())
  1695. return WBEM_E_OUT_OF_MEMORY;
  1696. // get the count.
  1697. DWORD dwNSCnt = GetNumNamespaces();
  1698. // check the parameters, index must be between 0 and count!
  1699. if(pszName == NULL || uIndex > dwNSCnt)
  1700. return WBEM_E_INVALID_PARAMETER;
  1701. // add this in.
  1702. CParsedComponent *pNew = new CParsedComponent(m_pCS);
  1703. if (pNew == NULL)
  1704. return WBEM_E_OUT_OF_MEMORY;
  1705. HRESULT hr = pNew->SetNS(pszName);
  1706. if(FAILED(hr))
  1707. {
  1708. delete pNew;
  1709. return hr;
  1710. }
  1711. int iRet = m_Components.InsertAt(uIndex, pNew);
  1712. if(iRet == CFlexArray::no_error)
  1713. return S_OK;
  1714. else
  1715. {
  1716. delete pNew;
  1717. return WBEM_E_OUT_OF_MEMORY;
  1718. }
  1719. }
  1720. /*++
  1721. Routine Description:
  1722. Gets a namespace name from the list
  1723. Arguments:
  1724. uIndex - zero based index. 0 if the leftmost.
  1725. uNameBufLength - size of pName in WCHAR
  1726. pName - caller supplied buffer where the data is to be copied
  1727. Return Value:
  1728. S_OK if all is well, else an error code.
  1729. --*/
  1730. HRESULT CDefPathParser::GetNamespaceAt(
  1731. /* [in] */ ULONG uIndex,
  1732. /* [in] */ ULONG * puNameBufLength,
  1733. /* [string][out] */ LPWSTR pName)
  1734. {
  1735. CSafeInCritSec cs(m_pCS->GetCS());
  1736. if(!cs.IsOK())
  1737. return WBEM_E_OUT_OF_MEMORY;
  1738. DWORD dwType;
  1739. if(uIndex >= (DWORD)GetNumNamespaces() || puNameBufLength == NULL || (*puNameBufLength > 0 && pName == NULL))
  1740. return WBEM_E_INVALID_PARAMETER;
  1741. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1742. BSTR bsName;
  1743. SCODE sc = pTemp->Unparse(&bsName, false, true);
  1744. if(FAILED(sc))
  1745. return sc;
  1746. CSysFreeMe fm(bsName);
  1747. DWORD dwSizeNeeded = wcslen(bsName)+1;
  1748. DWORD dwBuffSize = *puNameBufLength;
  1749. *puNameBufLength = dwSizeNeeded;
  1750. if(pName)
  1751. {
  1752. if(dwSizeNeeded > dwBuffSize)
  1753. return WBEM_E_BUFFER_TOO_SMALL;
  1754. wcscpy(pName, bsName);
  1755. }
  1756. return S_OK;
  1757. }
  1758. /*++
  1759. Routine Description:
  1760. Removes a namespace.
  1761. Arguments:
  1762. uIndex - 0 based index of namespace to be removed. 0 is the leftmost.
  1763. Return Value:
  1764. S_OK if all is well, else an error code.
  1765. --*/
  1766. HRESULT CDefPathParser::RemoveNamespaceAt(
  1767. /* [in] */ ULONG uIndex)
  1768. {
  1769. CSafeInCritSec cs(m_pCS->GetCS());
  1770. if(!cs.IsOK())
  1771. return WBEM_E_OUT_OF_MEMORY;
  1772. DWORD dwNSCnt;
  1773. GetNamespaceCount(&dwNSCnt);
  1774. // check the parameter, index must be between 0 and count-1!
  1775. if(uIndex >= dwNSCnt)
  1776. return WBEM_E_INVALID_PARAMETER;
  1777. // all is well, delete this
  1778. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1779. delete pTemp;
  1780. m_Components.RemoveAt(uIndex);
  1781. return S_OK;
  1782. }
  1783. /*++
  1784. Routine Description:
  1785. Removes all namespaces.
  1786. S_OK if all is well, else an error code.
  1787. --*/
  1788. HRESULT CDefPathParser::RemoveAllNamespaces()
  1789. {
  1790. CSafeInCritSec cs(m_pCS->GetCS());
  1791. if(!cs.IsOK())
  1792. return WBEM_E_OUT_OF_MEMORY;
  1793. DWORD dwNum = GetNumNamespaces();
  1794. for (DWORD dwIx = 0; dwIx < dwNum; dwIx++)
  1795. {
  1796. CParsedComponent * pNS = (CParsedComponent *)m_Components[0];
  1797. delete pNS;
  1798. m_Components.RemoveAt(0);
  1799. }
  1800. return S_OK;
  1801. }
  1802. /*++
  1803. Routine Description:
  1804. Gets the number of scopes
  1805. Arguments:
  1806. puCount - where the number is set.
  1807. Return Value:
  1808. S_OK if all is well, else an error code.
  1809. --*/
  1810. HRESULT CDefPathParser::GetScopeCount(/* [out] */ ULONG __RPC_FAR *puCount)
  1811. {
  1812. CSafeInCritSec cs(m_pCS->GetCS());
  1813. if(!cs.IsOK())
  1814. return WBEM_E_OUT_OF_MEMORY;
  1815. if(puCount == NULL)
  1816. return WBEM_E_INVALID_PARAMETER;
  1817. *puCount = m_Components.Size() - GetNumNamespaces();
  1818. return S_OK;
  1819. }
  1820. /*++
  1821. Routine Description:
  1822. Inserts a scope into the path. An index of 0 inserts it
  1823. at the front of the list. The maximum allowed value is equal
  1824. to the current number of scope which results in adding it
  1825. to the end of the list.
  1826. Arguments:
  1827. uIndex - See description
  1828. pszClass - Name of the new scope
  1829. Return Value:
  1830. S_OK if all is well, else an error code.
  1831. --*/
  1832. HRESULT CDefPathParser::SetScope(
  1833. /* [in] */ ULONG uIndex,
  1834. /* [in] */ LPWSTR pszClass)
  1835. {
  1836. CSafeInCritSec cs(m_pCS->GetCS());
  1837. if(!cs.IsOK())
  1838. return WBEM_E_OUT_OF_MEMORY;
  1839. DWORD dwScopeCnt = m_Components.Size();
  1840. uIndex += GetNumNamespaces();
  1841. if(pszClass == NULL || uIndex > dwScopeCnt)
  1842. return WBEM_E_INVALID_PARAMETER;
  1843. CParsedComponent *pNew = new CParsedComponent(m_pCS);
  1844. if(pNew == NULL)
  1845. return WBEM_E_OUT_OF_MEMORY;
  1846. pNew->m_sClassName = SysAllocString(pszClass);
  1847. if(pNew->m_sClassName == NULL)
  1848. {
  1849. delete pNew;
  1850. return WBEM_E_OUT_OF_MEMORY;
  1851. }
  1852. int iRet = m_Components.InsertAt(uIndex, pNew);
  1853. if(iRet == CFlexArray::no_error)
  1854. return S_OK;
  1855. else
  1856. {
  1857. delete pNew;
  1858. return WBEM_E_OUT_OF_MEMORY;
  1859. }
  1860. return S_OK;
  1861. }
  1862. HRESULT CDefPathParser::SetScopeFromText(
  1863. /* [in] */ ULONG uIndex,
  1864. /* [in] */ LPWSTR pszText)
  1865. {
  1866. return WBEM_E_NOT_AVAILABLE;
  1867. }
  1868. /*++
  1869. Routine Description:
  1870. Retrieves scope information.
  1871. Arguments:
  1872. uIndex - 0 based index. 0 is the leftmost scope
  1873. uClassNameBufSize - size of pszClass in WCHAR
  1874. pszClass - Optional, caller supplied buffer where name is to be copied
  1875. pKeyList - Optional, returns a pKeyList pointer. Caller must call Release.
  1876. Return Value:
  1877. S_OK if all is well, else an error code.
  1878. --*/
  1879. HRESULT CDefPathParser::GetScope(
  1880. /* [in] */ ULONG uIndex,
  1881. /* [in] */ ULONG * puClassNameBufSize,
  1882. /* [in] */ LPWSTR pszClass,
  1883. /* [out] */ IWbemPathKeyList __RPC_FAR *__RPC_FAR *pKeyList)
  1884. {
  1885. CSafeInCritSec cs(m_pCS->GetCS());
  1886. if(!cs.IsOK())
  1887. return WBEM_E_OUT_OF_MEMORY;
  1888. DWORD dwScopeCnt = m_Components.Size();
  1889. HRESULT hr = S_OK;
  1890. uIndex += GetNumNamespaces();
  1891. if(uIndex >= dwScopeCnt)
  1892. return WBEM_E_INVALID_PARAMETER;
  1893. if(puClassNameBufSize && (*puClassNameBufSize > 0 && pszClass == NULL))
  1894. return WBEM_E_INVALID_PARAMETER;
  1895. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1896. if(puClassNameBufSize)
  1897. {
  1898. BSTR bsName;
  1899. SCODE sc = pTemp->GetName(&bsName);
  1900. if(FAILED(sc))
  1901. {
  1902. return sc;
  1903. }
  1904. CSysFreeMe fm(bsName);
  1905. DWORD dwSizeNeeded = wcslen(bsName)+1;
  1906. DWORD dwBuffSize = *puClassNameBufSize;
  1907. *puClassNameBufSize = dwSizeNeeded;
  1908. if(pszClass)
  1909. {
  1910. if(dwSizeNeeded > dwBuffSize)
  1911. return WBEM_E_BUFFER_TOO_SMALL;
  1912. wcscpy(pszClass, bsName);
  1913. }
  1914. }
  1915. if(pKeyList)
  1916. {
  1917. hr = pTemp->QueryInterface(IID_IWbemPathKeyList, (void **)pKeyList);
  1918. if(FAILED(hr))
  1919. return hr;
  1920. }
  1921. return S_OK;
  1922. }
  1923. HRESULT CDefPathParser::GetScopeAsText(
  1924. /* [in] */ ULONG uIndex,
  1925. /* [out][in] */ ULONG __RPC_FAR *puTextBufSize,
  1926. /* [out][in] */ LPWSTR pszText)
  1927. {
  1928. CSafeInCritSec cs(m_pCS->GetCS());
  1929. if(!cs.IsOK())
  1930. return WBEM_E_OUT_OF_MEMORY;
  1931. DWORD dwScopeCnt = m_Components.Size();
  1932. uIndex += GetNumNamespaces();
  1933. if(uIndex >= dwScopeCnt || puTextBufSize == NULL)
  1934. return WBEM_E_INVALID_PARAMETER;
  1935. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1936. BSTR bstr;
  1937. HRESULT hr = pTemp->Unparse(&bstr, true, true);
  1938. if(FAILED(hr))
  1939. return hr;
  1940. CSysFreeMe fm(bstr);
  1941. DWORD dwBuffSize = *puTextBufSize;
  1942. DWORD dwSizeNeeded = wcslen(bstr)+1;
  1943. *puTextBufSize = dwSizeNeeded;
  1944. if(pszText)
  1945. {
  1946. if(dwSizeNeeded > dwBuffSize)
  1947. return WBEM_E_BUFFER_TOO_SMALL;
  1948. wcscpy(pszText, bstr);
  1949. }
  1950. return S_OK;
  1951. }
  1952. /*++
  1953. Routine Description:
  1954. Removes a scope.
  1955. Arguments:
  1956. uIndex - 0 based index. 0 is the leftmost scope.
  1957. Return Value:
  1958. S_OK if all is well, else an error code.
  1959. --*/
  1960. HRESULT CDefPathParser::RemoveScope(/* [in] */ ULONG uIndex)
  1961. {
  1962. HRESULT hr = S_OK;
  1963. CSafeInCritSec cs(m_pCS->GetCS());
  1964. if(!cs.IsOK())
  1965. return WBEM_E_OUT_OF_MEMORY;
  1966. bool bGotInterface = false;
  1967. uIndex += GetNumNamespaces();
  1968. if(uIndex >= (DWORD)m_Components.Size())
  1969. return WBEM_E_INVALID_PARAMETER;
  1970. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1971. pTemp->Release();
  1972. m_Components.RemoveAt(uIndex);
  1973. return S_OK;
  1974. }
  1975. /*++
  1976. Routine Description:
  1977. Removes all scopes.
  1978. Return Value:
  1979. S_OK if all is well, else an error code.
  1980. --*/
  1981. HRESULT CDefPathParser::RemoveAllScopes( void)
  1982. {
  1983. CSafeInCritSec cs(m_pCS->GetCS());
  1984. if(!cs.IsOK())
  1985. return WBEM_E_OUT_OF_MEMORY;
  1986. DWORD dwNumNS = GetNumNamespaces();
  1987. for (DWORD dwIx = dwNumNS; dwIx < (DWORD)m_Components.Size(); dwIx++)
  1988. {
  1989. CParsedComponent * pCom = (CParsedComponent *)m_Components[dwNumNS];
  1990. pCom->Release();
  1991. m_Components.RemoveAt(dwNumNS);
  1992. }
  1993. return S_OK;
  1994. }
  1995. /*++
  1996. Routine Description:
  1997. Sets the class name.
  1998. Arguments:
  1999. Name - New class name.
  2000. Return Value:
  2001. S_OK if all is well, else an error code.
  2002. --*/
  2003. HRESULT CDefPathParser::SetClassName(
  2004. /* [string][in] */ LPCWSTR Name)
  2005. {
  2006. CSafeInCritSec cs(m_pCS->GetCS());
  2007. if(!cs.IsOK())
  2008. return WBEM_E_OUT_OF_MEMORY;
  2009. if(Name == NULL)
  2010. return WBEM_E_INVALID_PARAMETER;
  2011. HRESULT hRes = WBEM_E_INVALID_OBJECT_PATH;
  2012. CParsedComponent * pClass = GetClass();
  2013. if (pClass)
  2014. {
  2015. if(pClass->m_sClassName)
  2016. SysFreeString(pClass->m_sClassName);
  2017. pClass->m_sClassName = NULL;
  2018. pClass->m_sClassName = SysAllocString(Name);
  2019. if(pClass->m_sClassName)
  2020. hRes = S_OK;
  2021. else
  2022. hRes = WBEM_E_OUT_OF_MEMORY;
  2023. }
  2024. else
  2025. hRes = CreateClassPart(0, Name);
  2026. return hRes;
  2027. }
  2028. /*++
  2029. Routine Description:
  2030. Gets the class name.
  2031. Arguments:
  2032. uBuffLength - size of pszName in WCHAR
  2033. pszName - caller supplied buffer where name is to be copied
  2034. Return Value:
  2035. S_OK if all is well, else an error code.
  2036. --*/
  2037. HRESULT CDefPathParser::GetClassName(
  2038. /* [in, out] */ ULONG * puBuffLength,
  2039. /* [string][out] */ LPWSTR pszName)
  2040. {
  2041. CSafeInCritSec cs(m_pCS->GetCS());
  2042. if(!cs.IsOK())
  2043. return WBEM_E_OUT_OF_MEMORY;
  2044. if(puBuffLength == NULL || (*puBuffLength > 0 && pszName == NULL))
  2045. return WBEM_E_INVALID_PARAMETER;
  2046. HRESULT hRes = WBEM_E_INVALID_OBJECT_PATH;
  2047. CParsedComponent * pClass = GetClass();
  2048. if (pClass && pClass->m_sClassName)
  2049. {
  2050. DWORD dwSizeNeeded = wcslen(pClass->m_sClassName) +1;
  2051. DWORD dwBuffSize = *puBuffLength;
  2052. *puBuffLength = dwSizeNeeded;
  2053. if(pszName)
  2054. {
  2055. if(dwSizeNeeded > dwBuffSize)
  2056. return WBEM_E_BUFFER_TOO_SMALL;
  2057. wcscpy(pszName, pClass->m_sClassName);
  2058. }
  2059. hRes = S_OK;
  2060. }
  2061. return hRes;
  2062. }
  2063. /*++
  2064. Routine Description:
  2065. Gets the key list pointer for the class key list.
  2066. Arguments:
  2067. pOut - Set to the key list. Caller must call Release on this.
  2068. Return Value:
  2069. S_OK if all is well, else an error code.
  2070. --*/
  2071. HRESULT CDefPathParser::GetKeyList(
  2072. /* [out] */ IWbemPathKeyList __RPC_FAR *__RPC_FAR *pOut)
  2073. {
  2074. CSafeInCritSec cs(m_pCS->GetCS());
  2075. if(!cs.IsOK())
  2076. return WBEM_E_OUT_OF_MEMORY;
  2077. HRESULT hRes = WBEM_E_NOT_AVAILABLE;
  2078. CParsedComponent * pClass = GetClass();
  2079. if(pOut == NULL || pClass == NULL)
  2080. return WBEM_E_INVALID_PARAMETER;
  2081. hRes = pClass->QueryInterface(IID_IWbemPathKeyList, (void **)pOut);
  2082. return hRes;
  2083. }
  2084. /*++
  2085. Routine Description:
  2086. Creates a class part of one does not exist.
  2087. Arguments:
  2088. lFlags - not used for now, set to 0
  2089. Name - name of the class
  2090. Return Value:
  2091. S_OK if all is well, else an error code.
  2092. --*/
  2093. HRESULT CDefPathParser::CreateClassPart(
  2094. /* [in] */ long lFlags,
  2095. /* [string][in] */ LPCWSTR Name)
  2096. {
  2097. CSafeInCritSec cs(m_pCS->GetCS());
  2098. if(!cs.IsOK())
  2099. return WBEM_E_OUT_OF_MEMORY;
  2100. if(lFlags != 0 || Name == NULL)
  2101. return WBEM_E_INVALID_PARAMETER;
  2102. CParsedComponent * pClass = new CParsedComponent(m_pCS);
  2103. if(pClass == NULL)
  2104. return WBEM_E_OUT_OF_MEMORY;
  2105. pClass->m_sClassName = SysAllocString(Name);
  2106. if(pClass->m_sClassName == NULL)
  2107. {
  2108. delete pClass;
  2109. return WBEM_E_OUT_OF_MEMORY;
  2110. }
  2111. m_Components.Add(pClass);
  2112. return S_OK;
  2113. }
  2114. /*++
  2115. Routine Description:
  2116. Deletes the class part.
  2117. Arguments:
  2118. lFlags - Not used for now, set to 0
  2119. Return Value:
  2120. S_OK if all is well, else an error code.
  2121. --*/
  2122. HRESULT CDefPathParser::DeleteClassPart(
  2123. /* [in] */ long lFlags)
  2124. {
  2125. CSafeInCritSec cs(m_pCS->GetCS());
  2126. if(!cs.IsOK())
  2127. return WBEM_E_OUT_OF_MEMORY;
  2128. CParsedComponent * pClass = GetClass();
  2129. if(lFlags != 0)
  2130. return WBEM_E_INVALID_PARAMETER;
  2131. if(pClass == NULL)
  2132. return WBEM_E_NOT_FOUND;
  2133. pClass->Release();
  2134. int iSize = m_Components.Size();
  2135. m_Components.RemoveAt(iSize-1);
  2136. return S_OK;
  2137. }
  2138. /*++
  2139. Routine Description:
  2140. Does the actual work of the "Relative" tests.
  2141. Arguments:
  2142. wszMachine - Local machine name
  2143. wszNamespace - Namespace
  2144. bChildreOK - If true, then it is OK if the obj
  2145. path has additional child namespaces
  2146. Return Value:
  2147. TRUE if relative, else false
  2148. --*/
  2149. BOOL CDefPathParser::ActualRelativeTest(
  2150. /* [string][in] */ LPWSTR wszMachine,
  2151. /* [string][in] */ LPWSTR wszNamespace,
  2152. BOOL bChildrenOK)
  2153. {
  2154. CSafeInCritSec cs(m_pCS->GetCS());
  2155. if(!cs.IsOK())
  2156. return WBEM_E_OUT_OF_MEMORY;
  2157. if(!IsLocal(wszMachine))
  2158. return FALSE;
  2159. DWORD dwNumNamespaces = GetNumNamespaces();
  2160. if(dwNumNamespaces == 0)
  2161. return TRUE;
  2162. LPWSTR wszCopy = new wchar_t[wcslen(wszNamespace) + 1];
  2163. if(wszCopy == NULL)return FALSE;
  2164. wcscpy(wszCopy, wszNamespace);
  2165. LPWSTR wszLeft = wszCopy;
  2166. WCHAR * pToFar = wszCopy + wcslen(wszCopy);
  2167. BOOL bFailed = FALSE;
  2168. for(DWORD i = 0; i < dwNumNamespaces; i++)
  2169. {
  2170. CParsedComponent * pInst = (CParsedComponent *)m_Components[i];
  2171. if(pInst == NULL)
  2172. {
  2173. bFailed = TRUE;
  2174. break;
  2175. }
  2176. BSTR bsNS = NULL;
  2177. HRESULT hr = pInst->Unparse(&bsNS, false, true);
  2178. if(FAILED(hr) || bsNS == NULL)
  2179. {
  2180. bFailed = TRUE;
  2181. break;
  2182. }
  2183. CSysFreeMe fm(bsNS);
  2184. if(bChildrenOK && wszLeft >= pToFar)
  2185. return TRUE;
  2186. unsigned int nLen = wcslen(bsNS);
  2187. if(nLen > wcslen(wszLeft))
  2188. {
  2189. bFailed = TRUE;
  2190. break;
  2191. }
  2192. if(i == dwNumNamespaces - 1 && wszLeft[nLen] != 0)
  2193. {
  2194. bFailed = TRUE;
  2195. break;
  2196. }
  2197. if(i != dwNumNamespaces - 1 && wszLeft[nLen] != L'\\' && bChildrenOK == FALSE)
  2198. {
  2199. bFailed = TRUE;
  2200. break;
  2201. }
  2202. wszLeft[nLen] = 0;
  2203. if(_wcsicmp(wszLeft, bsNS))
  2204. {
  2205. bFailed = TRUE;
  2206. break;
  2207. }
  2208. wszLeft += nLen+1;
  2209. }
  2210. delete [] wszCopy;
  2211. return !bFailed;
  2212. }
  2213. /*++
  2214. Routine Description:
  2215. Tests if path is relative to the machine and namespace.
  2216. Arguments:
  2217. wszMachine - Local machine name
  2218. wszNamespace - Namespace
  2219. Return Value:
  2220. TRUE if relative, else false
  2221. --*/
  2222. BOOL CDefPathParser::IsRelative(
  2223. /* [string][in] */ LPWSTR wszMachine,
  2224. /* [string][in] */ LPWSTR wszNamespace)
  2225. {
  2226. return ActualRelativeTest(wszMachine, wszNamespace, FALSE);
  2227. }
  2228. /*++
  2229. Routine Description:
  2230. Tests if path is relative to the machine and namespace.
  2231. Arguments:
  2232. wszMachine - Local machine name
  2233. wszNamespace - Namespace
  2234. lFlags - flags, not used for now.
  2235. Return Value:
  2236. TRUE if relative, or a child namespace. else false
  2237. --*/
  2238. BOOL CDefPathParser::IsRelativeOrChild(
  2239. /* [string][in] */ LPWSTR wszMachine,
  2240. /* [string][in] */ LPWSTR wszNamespace,
  2241. /* [in] */ long lFlags)
  2242. {
  2243. if(lFlags != 0)
  2244. return FALSE;
  2245. return ActualRelativeTest(wszMachine, wszNamespace, TRUE);
  2246. }
  2247. /*++
  2248. Routine Description:
  2249. Tests if path is to local machine
  2250. Arguments:
  2251. wszMachine - Local machine name
  2252. Return Value:
  2253. TRUE if local, else false
  2254. --*/
  2255. BOOL CDefPathParser::IsLocal(
  2256. /* [string][in] */ LPCWSTR wszMachine)
  2257. {
  2258. CSafeInCritSec cs(m_pCS->GetCS());
  2259. if(!cs.IsOK())
  2260. return WBEM_E_OUT_OF_MEMORY;
  2261. return (m_pServer == NULL || !_wcsicmp(m_pServer, L".") ||
  2262. !_wcsicmp(m_pServer, wszMachine));
  2263. }
  2264. /*++
  2265. Routine Description:
  2266. Tests if class name matches test
  2267. Arguments:
  2268. wszClassName - Local machine name
  2269. Return Value:
  2270. TRUE if local, else false
  2271. --*/
  2272. BOOL CDefPathParser::IsSameClassName(
  2273. /* [string][in] */ LPCWSTR wszClass)
  2274. {
  2275. CSafeInCritSec cs(m_pCS->GetCS());
  2276. if(!cs.IsOK())
  2277. return WBEM_E_OUT_OF_MEMORY;
  2278. CParsedComponent * pClass = GetClass();
  2279. if (pClass == NULL || pClass->m_sClassName == NULL || wszClass == NULL)
  2280. return FALSE;
  2281. return !_wcsicmp(pClass->m_sClassName, wszClass);
  2282. }
  2283. /*++
  2284. Routine Description:
  2285. Returns just the namspace part of the path
  2286. Return Value:
  2287. pointer to the result. Null if failer. Caller should free.
  2288. --*/
  2289. LPWSTR CDefPathParser::GetNamespacePart()
  2290. {
  2291. LPWSTR lpRet = NULL;
  2292. lpRet = GetPath(0, GetNumNamespaces());
  2293. return lpRet;
  2294. }
  2295. /*++
  2296. Routine Description:
  2297. Returns the parent namespace part.
  2298. Return Value:
  2299. pointer to the result. Null if failer. Caller should free.
  2300. --*/
  2301. LPWSTR CDefPathParser::GetParentNamespacePart()
  2302. {
  2303. DWORD dwNumNS = GetNumNamespaces();
  2304. if (dwNumNS < 2)
  2305. return NULL;
  2306. LPWSTR lpRet = NULL;
  2307. lpRet = GetPath(0, dwNumNS-1);
  2308. return lpRet;
  2309. }
  2310. long CDefPathParser::GetNumNamespaces()
  2311. {
  2312. long lRet = 0;
  2313. for(DWORD dwCnt = 0; dwCnt < (DWORD)m_Components.Size(); dwCnt++)
  2314. {
  2315. CParsedComponent * pInst = (CParsedComponent *)m_Components[dwCnt];
  2316. if(pInst->IsPossibleNamespace())
  2317. lRet++;
  2318. else
  2319. break;
  2320. }
  2321. return lRet;
  2322. }
  2323. /*++
  2324. Routine Description:
  2325. Sorts the keys based on the key name
  2326. Return Value:
  2327. TRUE if OK.
  2328. --*/
  2329. BOOL CDefPathParser::SortKeys()
  2330. {
  2331. // Sort the key refs lexically. If there is only
  2332. // one key, there is nothing to sort anyway.
  2333. // =============================================
  2334. BOOL bChanges = FALSE;
  2335. if (m_Components.Size())
  2336. {
  2337. CParsedComponent *pComp = GetLastComponent();
  2338. if (pComp)
  2339. {
  2340. CParsedComponent *pInst = (CParsedComponent *)pComp;
  2341. if (pInst->m_Keys.Size() > 1)
  2342. {
  2343. while (bChanges)
  2344. {
  2345. bChanges = FALSE;
  2346. for (DWORD dwIx = 0; dwIx < (DWORD)pInst->m_Keys.Size() - 1; dwIx++)
  2347. {
  2348. CKeyRef * pFirst = (CKeyRef *)pInst->m_Keys[dwIx];
  2349. CKeyRef * pSecond = (CKeyRef *)pInst->m_Keys[dwIx+1];
  2350. if (_wcsicmp(pFirst->m_pName, pSecond->m_pName) > 0)
  2351. {
  2352. pInst->m_Keys.SetAt(dwIx, pSecond);
  2353. pInst->m_Keys.SetAt(dwIx+1, pFirst);
  2354. bChanges = TRUE;
  2355. }
  2356. }
  2357. }
  2358. }
  2359. }
  2360. }
  2361. return bChanges;
  2362. }
  2363. HRESULT CDefPathParser::AddComponent(CParsedComponent * pComp)
  2364. {
  2365. if (CFlexArray::no_error == m_Components.Add(pComp))
  2366. return S_OK;
  2367. else
  2368. return WBEM_E_OUT_OF_MEMORY;
  2369. }