Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3111 lines
68 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 <string.h>
  13. #include "PathParse.h"
  14. #include "ActualParse.h"
  15. #include "commain.h"
  16. #include "wbemcli.h"
  17. #include <stdio.h>
  18. #include <sync.h>
  19. #include "helpers.h"
  20. extern long g_cObj;
  21. #ifndef STATUS_NO_MEMORY
  22. #define STATUS_NO_MEMORY ((DWORD)0xC0000017L) // winnt
  23. #endif
  24. CRefCntCS::CRefCntCS()
  25. {
  26. m_lRef = 1;
  27. m_Status = S_OK;
  28. __try
  29. {
  30. InitializeCriticalSection(&m_cs);
  31. }
  32. __except ((STATUS_NO_MEMORY == GetExceptionCode())?EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  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. StringCchPrintfW(lpKey,dwSize, L"%d", *(int *)m_pData);
  258. break;
  259. case CIM_UINT32:
  260. StringCchPrintfW(lpKey,dwSize, L"%u", *(unsigned *)m_pData);
  261. break;
  262. case CIM_SINT16:
  263. StringCchPrintfW(lpKey,dwSize, L"%hd", *(signed short *)m_pData);
  264. break;
  265. case CIM_UINT16:
  266. StringCchPrintfW(lpKey,dwSize, L"%hu", *(unsigned short *)m_pData);
  267. break;
  268. case CIM_SINT8:
  269. StringCchPrintfW(lpKey,dwSize, L"%d", *(signed char *)m_pData);
  270. break;
  271. case CIM_UINT8:
  272. StringCchPrintfW(lpKey,dwSize, L"%u", *(unsigned char *)m_pData);
  273. break;
  274. case CIM_UINT64:
  275. StringCchPrintfW(lpKey,dwSize, L"%I64u", *(unsigned __int64 *)m_pData);
  276. break;
  277. case CIM_SINT64:
  278. StringCchPrintfW(lpKey,dwSize, L"%I64d", *(__int64 *)m_pData);
  279. break;
  280. case CIM_BOOLEAN:
  281. if(*(int *)m_pData == 0)
  282. StringCchCopyW(lpKey,dwSize,L"false");
  283. else
  284. StringCchCopyW(lpKey,dwSize,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. StringCchCopyW(wszPath,nSpace, (const wchar_t *)m_sClassName);
  379. if (m_bSingleton)
  380. if(bUseClassName)
  381. StringCchCatW(wszPath,nSpace, L"=@");
  382. else
  383. StringCchCatW(wszPath,nSpace, 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. StringCchCatW(wszPath,nSpace, L".");
  394. }
  395. else
  396. {
  397. StringCchCatW(wszPath,nSpace, L",");
  398. }
  399. if(pKey->m_pName)
  400. {
  401. StringCchCatW(wszPath,nSpace, pKey->m_pName);
  402. }
  403. LPWSTR lpTemp = pKey->GetValue(bGetQuotes);
  404. if(lpTemp)
  405. {
  406. if(wcslen(wszPath))
  407. StringCchCatW(wszPath,nSpace, L"=");
  408. StringCchCatW(wszPath,nSpace, 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 && !wbem_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. {
  640. StringCchCopyW(pszKeyName,dwSizeNeeded, pKey->m_pName);
  641. }
  642. }
  643. }
  644. }
  645. if(puKeyValBufSize)
  646. {
  647. // get a pointer to the data and figure out how large it is
  648. DWORD dwSizeNeeded = 0;
  649. BYTE * pData = 0;
  650. bool bNeedToDelete = false;
  651. if(uFlags == 0)
  652. {
  653. dwSizeNeeded = pKey->m_dwSize;
  654. pData = (BYTE *)pKey->m_pData;
  655. }
  656. else
  657. {
  658. bool bQuoted = false;
  659. if(uFlags == WBEMPATH_QUOTEDTEXT)
  660. bQuoted = true;
  661. pData = (BYTE *)pKey->GetValue(bQuoted);
  662. if(pData == NULL)
  663. return WBEM_E_FAILED;
  664. bNeedToDelete = true;
  665. dwSizeNeeded = 2 * (wcslen((LPWSTR)pData)+1);
  666. }
  667. // Copy the data in
  668. if(*puKeyValBufSize < dwSizeNeeded && pKeyVal)
  669. {
  670. *puKeyValBufSize = dwSizeNeeded;
  671. if(bNeedToDelete)
  672. delete pData;
  673. return WBEM_E_BUFFER_TOO_SMALL;
  674. }
  675. *puKeyValBufSize = dwSizeNeeded;
  676. if(pData && pKeyVal)
  677. memcpy(pKeyVal, pData, dwSizeNeeded);
  678. if(bNeedToDelete)
  679. delete pData;
  680. }
  681. if(puApparentCimType)
  682. *puApparentCimType = pKey->m_dwType;
  683. if(bTooSmall)
  684. return WBEM_E_BUFFER_TOO_SMALL;
  685. else
  686. return S_OK;
  687. }
  688. /*++
  689. Routine Description:
  690. Gets the key information based on the key's index. Note that all return
  691. values are optional.
  692. Arguments:
  693. uKeyIx - Zero based index of the desired key
  694. uNameBufSize - size of buffer in WCHAR of pszKeyName
  695. pszKeyName - where name is to be copied. Can be NULL if not needed
  696. uKeyValBufSize - size of pKeyVal buffer in bytes
  697. pKeyVal - where data is to be copied. Can be NULL if not needed
  698. puApparentCimType - data type.
  699. Return Value:
  700. S_OK if all is well, else an error code.
  701. --*/
  702. HRESULT CParsedComponent::GetKey2(
  703. /* [in] */ ULONG uKeyIx,
  704. /* [in] */ ULONG uFlags,
  705. /* [out][in] */ ULONG __RPC_FAR *puNameBufSize,
  706. /* [out][in] */ LPWSTR pszKeyName,
  707. /* [out][in] */ VARIANT __RPC_FAR *pKeyValue,
  708. /* [out] */ ULONG __RPC_FAR *puApparentCimType)
  709. {
  710. DWORD dwSize = 50;
  711. WCHAR wTemp[50];
  712. CSafeInCritSec cs(m_pCS->GetCS());
  713. if(!cs.IsOK())
  714. return WBEM_E_OUT_OF_MEMORY;
  715. if(uKeyIx >= (DWORD)m_Keys.Size() || pKeyValue == NULL || puApparentCimType == NULL)
  716. return WBEM_E_INVALID_PARAMETER;
  717. CKeyRef * pKey = (CKeyRef *)m_Keys[uKeyIx];
  718. if(pKey->m_dwType == CIM_STRING || pKey->m_dwType == CIM_REFERENCE || pKey->m_dwType == CIM_DATETIME)
  719. dwSize = pKey->m_dwSize * 4 + 2;
  720. char * pTemp = new char[dwSize];
  721. if(pTemp == NULL)
  722. return WBEM_E_OUT_OF_MEMORY;
  723. CDeleteMe<char> dm(pTemp);
  724. HRESULT hr = GetKey(uKeyIx, uFlags, puNameBufSize,pszKeyName, &dwSize,
  725. (void *)pTemp, puApparentCimType);
  726. if(FAILED(hr))
  727. return hr;
  728. __int64 temp64;
  729. // convert to cim type;
  730. VariantClear(pKeyValue);
  731. switch (*puApparentCimType)
  732. {
  733. case CIM_STRING:
  734. case CIM_REFERENCE:
  735. case CIM_DATETIME:
  736. pKeyValue->vt = VT_BSTR;
  737. pKeyValue->bstrVal = SysAllocString((LPWSTR)pTemp);
  738. if(pKeyValue->bstrVal == NULL)
  739. return WBEM_E_OUT_OF_MEMORY;
  740. break;
  741. case CIM_UINT8:
  742. case CIM_SINT8:
  743. pKeyValue->vt = VT_UI1;
  744. memcpy((void*)&pKeyValue->lVal, pTemp, 1);
  745. break;
  746. case CIM_SINT16:
  747. case CIM_CHAR16:
  748. pKeyValue->vt = VT_I2;
  749. memcpy((void*)&pKeyValue->lVal, pTemp, 2);
  750. break;
  751. case CIM_UINT16:
  752. pKeyValue->vt = VT_I4;
  753. memcpy((void*)&pKeyValue->lVal, pTemp, 2);
  754. break;
  755. case CIM_SINT32:
  756. case CIM_UINT32:
  757. pKeyValue->vt = VT_I4;
  758. memcpy((void*)&pKeyValue->lVal, pTemp, 4);
  759. break;
  760. case CIM_BOOLEAN:
  761. pKeyValue->vt = VT_BOOL;
  762. memcpy((void*)&pKeyValue->lVal, pTemp, 4);
  763. break;
  764. case CIM_SINT64:
  765. case CIM_UINT64:
  766. memcpy((void *)&temp64, pTemp, 8);
  767. if(*puApparentCimType == CIM_SINT64)
  768. _i64tow(temp64, wTemp, 10);
  769. else
  770. _ui64tow(temp64, wTemp, 10);
  771. pKeyValue->vt = VT_BSTR;
  772. pKeyValue->bstrVal = SysAllocString(wTemp);
  773. if(pKeyValue->bstrVal == NULL)
  774. return WBEM_E_OUT_OF_MEMORY;
  775. break;
  776. }
  777. return hr;
  778. }
  779. /*++
  780. Routine Description:
  781. Removes a key from the key list.
  782. Arguments:
  783. wszName - Name of the key to be delete. Can be null if the key doesnt have a name.
  784. uFlags - not currently used.
  785. Return Value:
  786. S_OK if all is well, else an error code.
  787. --*/
  788. HRESULT CParsedComponent::RemoveKey(
  789. /* [string][in] */ LPCWSTR wszName,
  790. /* [in] */ ULONG uFlags)
  791. {
  792. CSafeInCritSec cs(m_pCS->GetCS());
  793. if(!cs.IsOK())
  794. return WBEM_E_OUT_OF_MEMORY;
  795. CKeyRef * pKey = NULL;
  796. bool bFound = false;
  797. DWORD dwCnt = 0;
  798. if(uFlags != 0)
  799. return WBEM_E_INVALID_PARAMETER;
  800. if(wszName == NULL || wszName[0] == 0)
  801. {
  802. // check for null key, it can match if single entry also null
  803. if(m_Keys.Size() == 1)
  804. {
  805. pKey = (CKeyRef *)m_Keys[dwCnt];
  806. if(pKey->m_pName == NULL || pKey->m_pName[0] == 0)
  807. bFound = true;
  808. }
  809. }
  810. else
  811. {
  812. // loop through and look for name match
  813. for(dwCnt = 0; dwCnt < (DWORD)m_Keys.Size(); dwCnt++)
  814. {
  815. pKey = (CKeyRef *)m_Keys[dwCnt];
  816. if(pKey->m_pName && !wbem_wcsicmp(pKey->m_pName, wszName))
  817. {
  818. bFound = true;
  819. break;
  820. }
  821. }
  822. }
  823. if(bFound)
  824. {
  825. delete pKey;
  826. m_Keys.RemoveAt(dwCnt);
  827. return S_OK;
  828. }
  829. else
  830. return WBEM_E_INVALID_PARAMETER;
  831. }
  832. /*++
  833. Routine Description:
  834. Removes all keys from the key list.
  835. Arguments:
  836. wszName - Name of the key to be delete. Can be null if the key doesnt have a name.
  837. uFlags - not currently used.
  838. Return Value:
  839. S_OK if all is well, else an error code.
  840. --*/
  841. HRESULT CParsedComponent::RemoveAllKeys(
  842. /* [in] */ ULONG uFlags)
  843. {
  844. CSafeInCritSec cs(m_pCS->GetCS());
  845. if(!cs.IsOK())
  846. return WBEM_E_OUT_OF_MEMORY;
  847. if(uFlags != 0)
  848. return WBEM_E_INVALID_PARAMETER;
  849. ClearKeys();
  850. return S_OK;
  851. }
  852. /*++
  853. Routine Description:
  854. Sets or unsets a key to be singleton.
  855. Arguments:
  856. bSet - if true, then all keys are deleted and the singleton flag is set.
  857. if false, then the singleton flag is cleared.
  858. Return Value:
  859. S_OK if all is well, else an error code.
  860. --*/
  861. HRESULT CParsedComponent::MakeSingleton(boolean bSet)
  862. {
  863. CSafeInCritSec cs(m_pCS->GetCS());
  864. if(!cs.IsOK())
  865. return WBEM_E_OUT_OF_MEMORY;
  866. if(bSet)
  867. {
  868. ClearKeys();
  869. m_bSingleton = true;
  870. }
  871. else
  872. m_bSingleton = false;
  873. return S_OK;
  874. }
  875. /*++
  876. Routine Description:
  877. Returns information about a particular key list.
  878. Arguments:
  879. uRequestedInfo - Not currently used, should be set to zero
  880. puResponse - any appropriate values will be OR'ed into this
  881. Return Value:
  882. S_OK if all is well, else an error code.
  883. --*/
  884. HRESULT CParsedComponent::GetInfo(
  885. /* [in] */ ULONG uRequestedInfo,
  886. /* [out] */ ULONGLONG __RPC_FAR *puResponse)
  887. {
  888. CSafeInCritSec cs(m_pCS->GetCS());
  889. if(!cs.IsOK())
  890. return WBEM_E_OUT_OF_MEMORY;
  891. if(uRequestedInfo != 0 || puResponse == NULL)
  892. return WBEM_E_INVALID_PARAMETER;
  893. *puResponse = 0;
  894. ULONG ulKeyCnt = m_Keys.Size();
  895. if(ulKeyCnt > 1)
  896. *puResponse |= WBEMPATH_INFO_IS_COMPOUND;
  897. for(DWORD dwKey = 0; dwKey < ulKeyCnt; dwKey++)
  898. {
  899. CKeyRef * pKey = (CKeyRef *)m_Keys[dwKey];
  900. if(pKey->m_pName == NULL || wcslen(pKey->m_pName) < 1)
  901. *puResponse |= WBEMPATH_INFO_HAS_IMPLIED_KEY;
  902. if(pKey->m_dwType == CIM_REFERENCE)
  903. *puResponse |= WBEMPATH_INFO_HAS_V2_REF_PATHS;
  904. }
  905. if(m_bSingleton)
  906. *puResponse |= WBEMPATH_INFO_CONTAINS_SINGLETON;
  907. return S_OK;
  908. }
  909. /*++
  910. Routine Description:
  911. Returns text version of a particular key list.
  912. Arguments:
  913. lFlags - 0 is only current value
  914. uBuffLength - number of WCHAR which can fit into pszText
  915. pszText - buffer supplied by caller where data is to be copied
  916. Return Value:
  917. S_OK if all is well, else an error code.
  918. --*/
  919. HRESULT CParsedComponent::GetText(
  920. /* [in] */ long lFlags,
  921. /* [out][in] */ ULONG __RPC_FAR *puBuffLength,
  922. /* [string][out] */ LPWSTR pszText)
  923. {
  924. CSafeInCritSec cs(m_pCS->GetCS());
  925. if(!cs.IsOK())
  926. return WBEM_E_OUT_OF_MEMORY;
  927. if((lFlags != 0 && lFlags != WBEMPATH_QUOTEDTEXT && lFlags != WBEMPATH_TEXT) || puBuffLength == NULL)
  928. return WBEM_E_INVALID_PARAMETER;
  929. BSTR data = NULL;
  930. bool bGetQuotes = false;
  931. if(lFlags & WBEMPATH_QUOTEDTEXT)
  932. bGetQuotes = true;
  933. HRESULT hr = Unparse(&data, bGetQuotes, false);
  934. if(FAILED(hr))
  935. return hr;
  936. if(data == NULL)
  937. return WBEM_E_FAILED;
  938. DWORD dwBuffSize = *puBuffLength;
  939. DWORD dwSizeNeeded = wcslen(data)+1;
  940. *puBuffLength = dwSizeNeeded;
  941. hr = S_OK;
  942. if(pszText)
  943. {
  944. if(dwSizeNeeded > dwBuffSize)
  945. hr = WBEM_E_BUFFER_TOO_SMALL;
  946. else
  947. {
  948. StringCchCopyW(pszText,dwSizeNeeded, data);
  949. }
  950. }
  951. SysFreeString(data);
  952. return hr;
  953. }
  954. /*++
  955. Routine Description:
  956. Cleans out a key list.
  957. --*/
  958. void CParsedComponent::ClearKeys ()
  959. {
  960. DWORD dwSize = m_Keys.Size();
  961. for ( ULONG dwDeleteIndex = 0 ; dwDeleteIndex < dwSize ;
  962. dwDeleteIndex ++ )
  963. {
  964. CKeyRef * pDel = (CKeyRef *)m_Keys[dwDeleteIndex];
  965. delete pDel;
  966. }
  967. m_Keys.Empty();
  968. }
  969. /*++
  970. Routine Description:
  971. Determines if the key list could be for an instance.
  972. Return Value:
  973. true if path has keys or is marked as singleton.
  974. --*/
  975. bool CParsedComponent::IsInstance()
  976. {
  977. if(m_bSingleton || m_Keys.Size())
  978. return true;
  979. else
  980. return false;
  981. }
  982. /*++
  983. Routine Description:
  984. Adds a key to the key list.
  985. Arguments:
  986. CKeyRef - key to be added. Note that it is now owned by the key list
  987. and should not be freed by the caller.
  988. Return Value:
  989. TRUE if all is well.
  990. --*/
  991. BOOL CParsedComponent::AddKeyRef(CKeyRef* pAcquireRef)
  992. {
  993. if(pAcquireRef == NULL)
  994. return FALSE;
  995. if(CFlexArray::no_error == m_Keys.Add(pAcquireRef))
  996. return TRUE;
  997. else
  998. return FALSE;
  999. }
  1000. /*++
  1001. Routine Description:
  1002. Tests a component to determine if it could be a namespace. That is true
  1003. only if it contains a single string value with no class name or key name.
  1004. Return Value:
  1005. TRUE if it could be a namespace.
  1006. --*/
  1007. bool CParsedComponent::IsPossibleNamespace()
  1008. {
  1009. if(m_sClassName && wcslen(m_sClassName))
  1010. return false;
  1011. if(m_Keys.Size() != 1)
  1012. return false;
  1013. CKeyRef * pKey = (CKeyRef *)m_Keys[0];
  1014. if(pKey->m_pName && wcslen(pKey->m_pName))
  1015. return false;
  1016. if(pKey->m_dwType != CIM_STRING)
  1017. return false;
  1018. if(pKey->m_pData == NULL)
  1019. return false;
  1020. else
  1021. return true;
  1022. }
  1023. /*++
  1024. Routine Description:
  1025. Sets a component to be a namespace.
  1026. Arguments:
  1027. pName - Name to be added.
  1028. Return Value:
  1029. S_OK if all is well, else standard error code.
  1030. --*/
  1031. HRESULT CParsedComponent::SetNS(LPCWSTR pName)
  1032. {
  1033. if(pName == NULL)
  1034. return WBEM_E_INVALID_PARAMETER;
  1035. CKeyRef * pNew = new CKeyRef;
  1036. if(pNew == NULL)
  1037. return WBEM_E_OUT_OF_MEMORY;
  1038. DWORD dwStrSize = wcslen(pName) + 1; // one for the numm
  1039. pNew->m_dwSize = 2 * dwStrSize; // size is in byte, not unicode
  1040. pNew->m_pData = new WCHAR[dwStrSize];
  1041. if(pNew->m_pData == NULL)
  1042. {
  1043. delete pNew;
  1044. return WBEM_E_OUT_OF_MEMORY;
  1045. }
  1046. StringCchCopyW((LPWSTR)pNew->m_pData,dwStrSize, pName);
  1047. pNew->m_dwType = CIM_STRING;
  1048. if(CFlexArray::no_error == m_Keys.Add(pNew))
  1049. return S_OK;
  1050. else
  1051. {
  1052. delete pNew;
  1053. return WBEM_E_OUT_OF_MEMORY;
  1054. }
  1055. }
  1056. //***************************************************************************
  1057. //
  1058. // CDefPathParser
  1059. //
  1060. //***************************************************************************
  1061. /*++
  1062. Routine Description:
  1063. Constructor.
  1064. --*/
  1065. CDefPathParser::CDefPathParser(void)
  1066. {
  1067. m_cRef=1;
  1068. m_pServer = 0; // NULL if no server
  1069. m_dwStatus = OK;
  1070. m_bParent = false;
  1071. m_pRawPath = NULL;
  1072. m_wszOriginalPath = NULL;
  1073. m_bSetViaUMIPath = false;
  1074. m_pCS = new CRefCntCS;
  1075. if(m_pCS == NULL || FAILED(m_pCS->GetStatus()))
  1076. m_dwStatus = FAILED_TO_INIT;
  1077. InterlockedIncrement(&g_cObj);
  1078. m_bServerNameSetByDefault = false;
  1079. m_pFTM = NULL;
  1080. CoCreateFreeThreadedMarshaler((IWbemPath*)this, &m_pFTM);
  1081. m_pGenLex = NULL;
  1082. m_dwException = 0;
  1083. return;
  1084. };
  1085. /*++
  1086. Routine Description:
  1087. Destructor.
  1088. --*/
  1089. CDefPathParser::~CDefPathParser(void)
  1090. {
  1091. if(m_pCS)
  1092. m_pCS->Release();
  1093. Empty();
  1094. m_pCS = NULL;
  1095. if(m_pFTM)
  1096. m_pFTM->Release();
  1097. InterlockedDecrement(&g_cObj);
  1098. return;
  1099. }
  1100. /*++
  1101. Routine Description:
  1102. Gets the total number of namespaces, scopes, and class parts.
  1103. Return Value:
  1104. Number of components.
  1105. --*/
  1106. DWORD CDefPathParser::GetNumComponents()
  1107. {
  1108. int iSize = m_Components.Size();
  1109. return iSize;
  1110. }
  1111. /*++
  1112. Routine Description:
  1113. Determines if there is anything in the path.
  1114. Return Value:
  1115. true if there is no server, namepace, scope or class part.
  1116. --*/
  1117. bool CDefPathParser::IsEmpty()
  1118. {
  1119. if(m_pServer || GetNumComponents() || m_pRawPath)
  1120. return false;
  1121. else
  1122. return true;
  1123. }
  1124. /*++
  1125. Routine Description:
  1126. Cleans out the data. Used by destructor.
  1127. --*/
  1128. void CDefPathParser::Empty(void)
  1129. {
  1130. m_bSetViaUMIPath = false;
  1131. delete m_pServer;
  1132. m_bParent = false;
  1133. m_pServer = NULL;
  1134. delete m_pRawPath;
  1135. m_pRawPath = NULL;
  1136. delete m_wszOriginalPath;
  1137. m_wszOriginalPath = NULL;
  1138. for (DWORD dwIx = 0; dwIx < (DWORD)m_Components.Size(); dwIx++)
  1139. {
  1140. CParsedComponent * pCom = (CParsedComponent *)m_Components[dwIx];
  1141. pCom->Release();
  1142. }
  1143. m_Components.Empty();
  1144. return;
  1145. }
  1146. /*++
  1147. Routine Description:
  1148. Gets the component string. The string varies depending on if the component
  1149. if a namepace, or scope or path.
  1150. Arguments:
  1151. i - zero based index
  1152. pUnparsed - where the string is returned. The caller must free via SysFreeString.
  1153. wDelim - Delimiter for this type
  1154. Return Value:
  1155. S_OK if all is well, else an error code.
  1156. --*/
  1157. HRESULT CDefPathParser::GetComponentString(ULONG i, BSTR * pUnparsed, WCHAR & wDelim)
  1158. {
  1159. DWORD dwNs = GetNumNamespaces();
  1160. DWORD dwSc = m_Components.Size();
  1161. if(i < dwNs)
  1162. {
  1163. CParsedComponent * pNS = (CParsedComponent *)m_Components[i];
  1164. wDelim = L'\\';
  1165. return pNS->Unparse(pUnparsed, false, true);
  1166. }
  1167. CParsedComponent * pInst = NULL;
  1168. if(i < (dwSc))
  1169. pInst = (CParsedComponent *)m_Components[i];
  1170. if(pInst == NULL)
  1171. return WBEM_E_INVALID_PARAMETER;
  1172. wDelim = L':';
  1173. HRESULT hRes;
  1174. hRes = pInst->Unparse(pUnparsed, true, true);
  1175. return hRes;
  1176. }
  1177. /*++
  1178. Routine Description:
  1179. Returns the path
  1180. Arguments:
  1181. nStartAt - first component to be added to the path
  1182. nStopAt - last component to be added to the path. Note that this is usually just set to
  1183. the number of components.
  1184. Return Value:
  1185. pointer to the string. The caller must free this via delete. If there is an Error, NULL is returned.
  1186. --*/
  1187. LPWSTR CDefPathParser::GetPath(DWORD nStartAt, DWORD nStopAt,bool bGetServer)
  1188. {
  1189. DWORD dwSize = 1024, dwUsed = 0;
  1190. if(bGetServer && m_pServer && wcslen(m_pServer) > 1000)
  1191. dwSize = 2 * wcslen(m_pServer);
  1192. LPWSTR wszOut = new WCHAR[dwSize];
  1193. if(wszOut == NULL)
  1194. return NULL;
  1195. wszOut[0] = 0;
  1196. bool bFirst = true;
  1197. if(bGetServer && m_pServer && wcslen(m_pServer) < 1020)
  1198. {
  1199. int iLen = wcslen(m_pServer) + 3; // allow for back slashes
  1200. StringCchCopyW(wszOut,dwSize, L"\\\\");
  1201. StringCchCatW(wszOut,dwSize, m_pServer);
  1202. StringCchCatW(wszOut,dwSize, L"\\");
  1203. dwUsed = iLen;
  1204. }
  1205. for (unsigned int i = nStartAt; (int)i < (int)nStopAt; i++)
  1206. {
  1207. BSTR sTemp = NULL;
  1208. WCHAR wDel;
  1209. HRESULT hRes = GetComponentString(i, &sTemp, wDel);
  1210. if(FAILED(hRes))
  1211. {
  1212. delete wszOut;
  1213. return NULL;
  1214. }
  1215. CSysFreeMe fm(sTemp);
  1216. int iLen = wcslen(sTemp);
  1217. if ((iLen + dwUsed) > (dwSize-2))
  1218. {
  1219. DWORD dwNewSize = 2*(dwSize + iLen);
  1220. LPWSTR lpTemp = new WCHAR[dwNewSize];
  1221. CDeleteMe<WCHAR> dm(wszOut);
  1222. if(lpTemp == NULL)
  1223. return NULL;
  1224. memcpy(lpTemp,wszOut, dwSize * sizeof(WCHAR));
  1225. dwSize = dwNewSize;
  1226. wszOut = lpTemp;
  1227. }
  1228. if (!bFirst)
  1229. {
  1230. int n = wcslen(wszOut);
  1231. wszOut[n] = wDel;
  1232. wszOut[n+1] = '\0';
  1233. iLen++;
  1234. }
  1235. bFirst = false;
  1236. StringCchCatW(wszOut,dwSize, sTemp);
  1237. dwUsed += iLen;
  1238. }
  1239. return wszOut;
  1240. }
  1241. /*++
  1242. Routine Description:
  1243. Adds a namespace.
  1244. Arguments:
  1245. wszNamespace - Name to be set into the namespace.
  1246. Return Value:
  1247. TRUE if all is well.
  1248. --*/
  1249. BOOL CDefPathParser::AddNamespace(LPCWSTR wszNamespace)
  1250. {
  1251. BOOL bRet = FALSE;
  1252. DWORD dwNumNS = GetNumNamespaces();
  1253. CParsedComponent *pNew = new CParsedComponent(m_pCS);
  1254. if (pNew)
  1255. {
  1256. HRESULT hr = pNew->SetNS(wszNamespace);
  1257. if(FAILED(hr))
  1258. {
  1259. delete pNew;
  1260. return FALSE;
  1261. }
  1262. int iRet = m_Components.InsertAt(dwNumNS, pNew);
  1263. if(iRet != CFlexArray::no_error)
  1264. {
  1265. delete pNew;
  1266. bRet = FALSE;
  1267. }
  1268. else
  1269. bRet = TRUE;
  1270. }
  1271. return bRet;
  1272. }
  1273. /*++
  1274. Routine Description:
  1275. This is used during the parsing of the path and is
  1276. just a convenient way to get at the last scope. Note
  1277. that during this phase, the class part is in the scope
  1278. list.
  1279. Return Value:
  1280. pointer to last scope or NULL if there isnt one.
  1281. --*/
  1282. CParsedComponent * CDefPathParser::GetLastComponent()
  1283. {
  1284. DWORD dwSize = m_Components.Size();
  1285. if (dwSize > (DWORD)GetNumNamespaces())
  1286. return (CParsedComponent *)m_Components[dwSize-1];
  1287. else
  1288. return NULL;
  1289. }
  1290. /*++
  1291. Routine Description:
  1292. Adds new class. This is used during the parsing stage when
  1293. the class is just treated as the last scope.
  1294. Arguments:
  1295. lpClassName - Name of the class
  1296. Return Value:
  1297. TRUE if ok
  1298. --*/
  1299. BOOL CDefPathParser::AddClass(LPCWSTR lpClassName)
  1300. {
  1301. BOOL bRet = FALSE;
  1302. CParsedComponent *pNew = new CParsedComponent(m_pCS);
  1303. if (pNew)
  1304. {
  1305. pNew->m_sClassName = SysAllocString(lpClassName);
  1306. if(pNew->m_sClassName)
  1307. {
  1308. m_Components.Add(pNew);
  1309. bRet = TRUE;
  1310. }
  1311. else
  1312. delete pNew;
  1313. }
  1314. return bRet;
  1315. }
  1316. /*++
  1317. Routine Description:
  1318. Adds a key/value pair.
  1319. Arguments:
  1320. pKey - Data to be added. Note that this is acquired by this routine.
  1321. Return Value:
  1322. TRUE if all is well
  1323. --*/
  1324. BOOL CDefPathParser::AddKeyRef(CKeyRef *pRef)
  1325. {
  1326. BOOL bRet = FALSE;
  1327. CParsedComponent *pTemp = GetLastComponent();
  1328. if (pTemp)
  1329. {
  1330. DWORD dwType = 0;
  1331. bRet = pTemp->AddKeyRef(pRef);
  1332. }
  1333. return bRet;
  1334. }
  1335. /*++
  1336. Routine Description:
  1337. Sets the most recent class to be singleton.
  1338. Return Value:
  1339. TRUE if OK.
  1340. --*/
  1341. BOOL CDefPathParser::SetSingletonObj()
  1342. {
  1343. BOOL bRet = FALSE;
  1344. CParsedComponent *pTemp = GetLastComponent();
  1345. if (pTemp)
  1346. pTemp->MakeSingleton(true);
  1347. return bRet;
  1348. }
  1349. /*++
  1350. Routine Description:
  1351. Sets the path text. This causes object to be emptied, the path to be parsed
  1352. and the object be rebuilt.
  1353. Arguments:
  1354. uMode - mode, can be
  1355. WBEMPATH_CREATE_ACCEPT_RELATIVE
  1356. WBEMPATH_CREATE_ACCEPT_ABSOLUTE
  1357. WBEMPATH_CREATE_ACCEPT_ALL
  1358. pszPath - Path.
  1359. Return Value:
  1360. S_OK if all is well, else an error code.
  1361. --*/
  1362. HRESULT CDefPathParser::SetText(
  1363. /* [in] */ ULONG uMode,
  1364. /* [in] */ LPCWSTR pszPath)
  1365. {
  1366. CSafeInCritSec cs(m_pCS->GetCS());
  1367. if(!cs.IsOK())
  1368. return WBEM_E_OUT_OF_MEMORY;
  1369. if(pszPath == NULL)
  1370. return WBEM_E_INVALID_PARAMETER;
  1371. if(!IsEmpty())
  1372. Empty();
  1373. if ((uMode & WBEMPATH_CREATE_ACCEPT_ALL) != 0 && wcslen (pszPath) == 0)
  1374. return S_OK;
  1375. try
  1376. {
  1377. size_t cchTmp = wcslen(pszPath)+1;
  1378. m_wszOriginalPath = new WCHAR[cchTmp];
  1379. if(m_wszOriginalPath)
  1380. {
  1381. StringCchCopyW(m_wszOriginalPath,cchTmp, pszPath);
  1382. if(wcscmp(pszPath, L"..") == 0)
  1383. {
  1384. m_bParent = true;
  1385. m_dwStatus = OK;
  1386. return S_OK;
  1387. }
  1388. // normal case
  1389. CActualPathParser parser(uMode);
  1390. int iRet = parser.Parse(pszPath, *this);
  1391. if(iRet == 0)
  1392. {
  1393. m_dwStatus = OK;
  1394. return S_OK;
  1395. }
  1396. else
  1397. {
  1398. m_dwStatus = BAD_STRING;
  1399. return WBEM_E_INVALID_PARAMETER;
  1400. }
  1401. }
  1402. else
  1403. {
  1404. return WBEM_E_OUT_OF_MEMORY;
  1405. }
  1406. }
  1407. catch(...)
  1408. {
  1409. m_dwStatus = EXECEPTION_THROWN;
  1410. return WBEM_E_CRITICAL_ERROR;
  1411. }
  1412. }
  1413. /*++
  1414. Routine Description:
  1415. Create a WMI path from the object
  1416. Arguments:
  1417. lFlags - 0
  1418. uBuffLength - number of WCHAR which can fit into pszText
  1419. pszText - buffer supplied by caller where data is to be copied
  1420. Return Value:
  1421. S_OK if all is well, else an error code.
  1422. --*/
  1423. HRESULT CDefPathParser::GetText(
  1424. /* [in] */ long lFlags,
  1425. /* [in] */ ULONG * puBuffLength,
  1426. /* [string][out] */ LPWSTR pszText)
  1427. {
  1428. CSafeInCritSec cs(m_pCS->GetCS());
  1429. if(!cs.IsOK())
  1430. return WBEM_E_OUT_OF_MEMORY;
  1431. if(puBuffLength == NULL || (*puBuffLength > 0 &&pszText == NULL))
  1432. return WBEM_E_INVALID_PARAMETER;
  1433. if(lFlags != 0 && lFlags != WBEMPATH_GET_RELATIVE_ONLY && lFlags != WBEMPATH_GET_SERVER_TOO &&
  1434. lFlags != WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY && lFlags != WBEMPATH_GET_NAMESPACE_ONLY &&
  1435. lFlags != WBEMPATH_GET_ORIGINAL)
  1436. return WBEM_E_INVALID_PARAMETER;
  1437. if(lFlags == WBEMPATH_GET_ORIGINAL && m_wszOriginalPath)
  1438. {
  1439. DWORD dwSizeNeeded = wcslen(m_wszOriginalPath) + 1;
  1440. DWORD dwBuffSize = *puBuffLength;
  1441. *puBuffLength = dwSizeNeeded;
  1442. if(pszText)
  1443. {
  1444. if(dwSizeNeeded > dwBuffSize)
  1445. return WBEM_E_BUFFER_TOO_SMALL;
  1446. StringCchCopyW(pszText,dwSizeNeeded, m_wszOriginalPath);
  1447. }
  1448. return S_OK;
  1449. }
  1450. LPWSTR pTemp = NULL;
  1451. DWORD dwStartAt = 0;
  1452. if(lFlags & WBEMPATH_GET_RELATIVE_ONLY)
  1453. dwStartAt = GetNumNamespaces();
  1454. bool bGetServer = false;
  1455. if(lFlags & WBEMPATH_GET_SERVER_TOO || lFlags & WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY)
  1456. bGetServer = true;
  1457. DWORD dwNum;
  1458. if(lFlags & WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY ||
  1459. lFlags & WBEMPATH_GET_NAMESPACE_ONLY)
  1460. dwNum = GetNumNamespaces();
  1461. else
  1462. dwNum = GetNumComponents();
  1463. // If just a relative path is specified, then dont prepend the server since that
  1464. // will create an invalid path
  1465. if(bGetServer && GetNumNamespaces() == 0 && m_bServerNameSetByDefault == true)
  1466. bGetServer = false;
  1467. pTemp = GetPath(dwStartAt, dwNum, bGetServer);
  1468. if(pTemp == NULL)
  1469. return WBEM_E_FAILED;
  1470. CDeleteMe<WCHAR> dm(pTemp);
  1471. DWORD dwSizeNeeded = wcslen(pTemp) + 1;
  1472. DWORD dwBuffSize = *puBuffLength;
  1473. *puBuffLength = dwSizeNeeded;
  1474. if(pszText)
  1475. {
  1476. if(dwSizeNeeded > dwBuffSize)
  1477. return WBEM_E_BUFFER_TOO_SMALL;
  1478. StringCchCopyW(pszText,dwSizeNeeded, pTemp);
  1479. }
  1480. return S_OK;
  1481. }
  1482. CParsedComponent * CDefPathParser::GetClass()
  1483. {
  1484. DWORD dwNS = GetNumNamespaces();
  1485. DWORD dwScopes = m_Components.Size() - dwNS;
  1486. if(dwScopes < 1)
  1487. return NULL;
  1488. int iLast = m_Components.Size()-1;
  1489. return (CParsedComponent *)m_Components.GetAt(iLast);
  1490. }
  1491. /*++
  1492. Routine Description:
  1493. Gets information about the object path.
  1494. Arguments:
  1495. uRequestedInfo - Must be zero for now
  1496. puResponse - The various flags in tag_WMI_PATH_STATUS_FLAG are
  1497. OR'ed in as appropriate.
  1498. Return Value:
  1499. S_OK if all is well, else an error code.
  1500. --*/
  1501. HRESULT CDefPathParser::GetInfo(/* [in] */ ULONG uRequestedInfo,
  1502. /* [out] */ ULONGLONG __RPC_FAR *puResponse)
  1503. {
  1504. CSafeInCritSec cs(m_pCS->GetCS());
  1505. if(!cs.IsOK())
  1506. return WBEM_E_OUT_OF_MEMORY;
  1507. if(uRequestedInfo != 0 || puResponse == NULL)
  1508. return WBEM_E_INVALID_PARAMETER;
  1509. *puResponse = 0;
  1510. // special case for ".." paths.
  1511. if(IsEmpty() && m_bParent)
  1512. {
  1513. *puResponse |= WBEMPATH_INFO_IS_PARENT;
  1514. return S_OK;
  1515. }
  1516. // bits for
  1517. // WBEMPATH_INFO_NATIVE_PATH = 0X8000,
  1518. // WBEMPATH_INFO_WMI_PATH = 0X10000,
  1519. if(m_bSetViaUMIPath)
  1520. *puResponse |= WBEMPATH_INFO_WMI_PATH;
  1521. if(m_pRawPath)
  1522. *puResponse |= WBEMPATH_INFO_NATIVE_PATH;
  1523. // Bits for
  1524. // WBEMPATH_INFO_ANON_LOCAL_MACHINE <path has \\. as server name>
  1525. // WBEMPATH_INFO_HAS_MACHINE_NAME <not a dot>
  1526. // WBEMPATH_INFO_PATH_HAD_SERVER <there is a path and it was not specified by default>
  1527. if(m_pServer == NULL || !wbem_wcsicmp(m_pServer, L"."))
  1528. *puResponse |= WBEMPATH_INFO_ANON_LOCAL_MACHINE;
  1529. else
  1530. *puResponse |= WBEMPATH_INFO_HAS_MACHINE_NAME;
  1531. if(m_pServer && m_bServerNameSetByDefault == false)
  1532. *puResponse |= WBEMPATH_INFO_PATH_HAD_SERVER;
  1533. // WBEMPATH_INFO_HAS_SUBSCOPES <true if a subscope is present
  1534. DWORD dwNS = GetNumNamespaces();
  1535. DWORD dwScopes = m_Components.Size() - dwNS;
  1536. if(dwScopes)
  1537. *puResponse |= WBEMPATH_INFO_HAS_SUBSCOPES;
  1538. // Bits for
  1539. // WBEMPATH_INFO_IS_CLASS_REF <a path to a classs, not a path to an instance
  1540. // WBEMPATH_INFO_IS_INST_REF <a path to an instance
  1541. CParsedComponent * pClass = GetClass();
  1542. if (pClass)
  1543. {
  1544. DWORD dwType = 0;
  1545. if(pClass->IsInstance())
  1546. *puResponse |= WBEMPATH_INFO_IS_INST_REF;
  1547. else
  1548. *puResponse |= WBEMPATH_INFO_IS_CLASS_REF;
  1549. if(pClass->m_bSingleton)
  1550. *puResponse |= WBEMPATH_INFO_IS_SINGLETON;
  1551. }
  1552. else
  1553. if(dwScopes == 0)
  1554. *puResponse |= WBEMPATH_INFO_SERVER_NAMESPACE_ONLY;
  1555. // loop through all the scopes and the class deff.
  1556. // set the following
  1557. // WBEMPATH_INFO_IS_COMPOUND <true if compound key is used
  1558. // WBEMPATH_INFO_HAS_V2_REF_PATHS <true if V2-style ref paths are used
  1559. // WBEMPATH_INFO_HAS_IMPLIED_KEY <true if keynames are missing somewhere
  1560. // WBEMPATH_INFO_CONTAINS_SINGLETON <true if one or more singletons
  1561. unsigned __int64 llRet = 0;
  1562. for (unsigned int iCnt = dwNS; iCnt < (DWORD)m_Components.Size(); iCnt++)
  1563. {
  1564. CParsedComponent *pComp = (CParsedComponent *)m_Components[iCnt];
  1565. pComp->GetInfo(0, &llRet);
  1566. *puResponse |= llRet;
  1567. }
  1568. if(pClass)
  1569. {
  1570. pClass->GetInfo(0, &llRet);
  1571. *puResponse |= llRet;
  1572. }
  1573. // For now, assume that v1 compilance means no scopes or new references
  1574. bool bOK = (!IsEmpty() && m_dwStatus == OK);
  1575. if(dwScopes == 0 && (*puResponse & WBEMPATH_INFO_HAS_V2_REF_PATHS) == 0 && bOK)
  1576. *puResponse |= WBEMPATH_INFO_V1_COMPLIANT;
  1577. // WBEMPATH_INFO_V2_COMPLIANT <true if path is WMI-V2-compliant
  1578. // WBEMPATH_INFO_CIM_COMPLIANT <true if path is CIM-compliant
  1579. if(bOK)
  1580. {
  1581. // todo, need to define cim compliance
  1582. *puResponse |= WBEMPATH_INFO_V2_COMPLIANT;
  1583. *puResponse |= WBEMPATH_INFO_CIM_COMPLIANT;
  1584. }
  1585. return S_OK;
  1586. }
  1587. /*++
  1588. Routine Description:
  1589. Sets the server portion of the path.
  1590. Arguments:
  1591. Name - New server name.
  1592. Return Value:
  1593. S_OK if all is well, else an error code.
  1594. --*/
  1595. HRESULT CDefPathParser::SetServer(
  1596. /* [string][in] */ LPCWSTR Name)
  1597. {
  1598. return SetServer(Name, false, false);
  1599. }
  1600. HRESULT CDefPathParser::SetServer(
  1601. /* [string][in] */ LPCWSTR Name, bool bServerNameSetByDefault, bool bAcquire)
  1602. {
  1603. m_bServerNameSetByDefault = bServerNameSetByDefault;
  1604. CSafeInCritSec cs(m_pCS->GetCS());
  1605. if(!cs.IsOK())
  1606. return WBEM_E_OUT_OF_MEMORY;
  1607. delete m_pServer;
  1608. m_pServer = NULL;
  1609. if(Name == NULL) // it is ok to have a null server an
  1610. return S_OK;
  1611. if(bAcquire)
  1612. {
  1613. m_pServer = (LPWSTR)Name;
  1614. }
  1615. else
  1616. {
  1617. size_t cchTmp = wcslen(Name)+1;
  1618. m_pServer = new WCHAR[cchTmp];
  1619. if(m_pServer == NULL)
  1620. return WBEM_E_OUT_OF_MEMORY;
  1621. StringCchCopyW(m_pServer,cchTmp, Name);
  1622. }
  1623. return S_OK;
  1624. }
  1625. /*++
  1626. Routine Description:
  1627. Gets the server portion of the path
  1628. Arguments:
  1629. puNameBufLength - size of pName in WCHAR. On return, set to size used or needed
  1630. pName - caller allocated buffer where date is to be copied
  1631. Return Value:
  1632. S_OK if all is well, else an error code.
  1633. --*/
  1634. HRESULT CDefPathParser::GetServer(
  1635. /* [out][in] */ ULONG __RPC_FAR *puNameBufLength,
  1636. /* [string][out] */ LPWSTR pName)
  1637. {
  1638. CSafeInCritSec cs(m_pCS->GetCS());
  1639. if(!cs.IsOK())
  1640. return WBEM_E_OUT_OF_MEMORY;
  1641. if(puNameBufLength == 0 || (*puNameBufLength > 0 && pName == NULL))
  1642. return WBEM_E_INVALID_PARAMETER;
  1643. if(m_pServer == NULL)
  1644. return WBEM_E_NOT_AVAILABLE;
  1645. DWORD dwSizeNeeded = wcslen(m_pServer)+1;
  1646. DWORD dwBuffSize = *puNameBufLength;
  1647. *puNameBufLength = dwSizeNeeded;
  1648. if(pName)
  1649. {
  1650. if(dwSizeNeeded > dwBuffSize)
  1651. return WBEM_E_BUFFER_TOO_SMALL;
  1652. StringCchCopyW(pName,dwSizeNeeded, m_pServer);
  1653. }
  1654. return S_OK;
  1655. }
  1656. /*++
  1657. Routine Description:
  1658. Gets the number of namespaces
  1659. Arguments:
  1660. puCount - Set to the number of namespaces.
  1661. Return Value:
  1662. S_OK if all is well, else an error code.
  1663. --*/
  1664. HRESULT CDefPathParser::GetNamespaceCount(
  1665. /* [out] */ ULONG __RPC_FAR *puCount)
  1666. {
  1667. CSafeInCritSec cs(m_pCS->GetCS());
  1668. if(!cs.IsOK())
  1669. return WBEM_E_OUT_OF_MEMORY;
  1670. if(puCount == NULL)
  1671. return WBEM_E_INVALID_PARAMETER;
  1672. *puCount = GetNumNamespaces();
  1673. return S_OK;
  1674. }
  1675. /*++
  1676. Routine Description:
  1677. Inserts a namespace into the path. An index of 0 inserts it
  1678. at the front of the list. The maximum allowed value is equal
  1679. to the current number of namespaces which results in adding it
  1680. to the end of the list.
  1681. Arguments:
  1682. uIndex - See above
  1683. pszName - Name of the new Namespace
  1684. Return Value:
  1685. S_OK if all is well, else an error code.
  1686. --*/
  1687. HRESULT CDefPathParser::SetNamespaceAt(/* [in] */ ULONG uIndex,
  1688. /* [string][in] */ LPCWSTR pszName)
  1689. {
  1690. CSafeInCritSec cs(m_pCS->GetCS());
  1691. if(!cs.IsOK())
  1692. return WBEM_E_OUT_OF_MEMORY;
  1693. // get the count.
  1694. DWORD dwNSCnt = GetNumNamespaces();
  1695. // check the parameters, index must be between 0 and count!
  1696. if(pszName == NULL || uIndex > dwNSCnt)
  1697. return WBEM_E_INVALID_PARAMETER;
  1698. // add this in.
  1699. CParsedComponent *pNew = new CParsedComponent(m_pCS);
  1700. if (pNew == NULL)
  1701. return WBEM_E_OUT_OF_MEMORY;
  1702. HRESULT hr = pNew->SetNS(pszName);
  1703. if(FAILED(hr))
  1704. {
  1705. delete pNew;
  1706. return hr;
  1707. }
  1708. int iRet = m_Components.InsertAt(uIndex, pNew);
  1709. if(iRet == CFlexArray::no_error)
  1710. return S_OK;
  1711. else
  1712. {
  1713. delete pNew;
  1714. return WBEM_E_OUT_OF_MEMORY;
  1715. }
  1716. }
  1717. /*++
  1718. Routine Description:
  1719. Gets a namespace name from the list
  1720. Arguments:
  1721. uIndex - zero based index. 0 if the leftmost.
  1722. uNameBufLength - size of pName in WCHAR
  1723. pName - caller supplied buffer where the data is to be copied
  1724. Return Value:
  1725. S_OK if all is well, else an error code.
  1726. --*/
  1727. HRESULT CDefPathParser::GetNamespaceAt(
  1728. /* [in] */ ULONG uIndex,
  1729. /* [in] */ ULONG * puNameBufLength,
  1730. /* [string][out] */ LPWSTR pName)
  1731. {
  1732. CSafeInCritSec cs(m_pCS->GetCS());
  1733. if(!cs.IsOK())
  1734. return WBEM_E_OUT_OF_MEMORY;
  1735. DWORD dwType;
  1736. if(uIndex >= (DWORD)GetNumNamespaces() || puNameBufLength == NULL || (*puNameBufLength > 0 && pName == NULL))
  1737. return WBEM_E_INVALID_PARAMETER;
  1738. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1739. BSTR bsName;
  1740. SCODE sc = pTemp->Unparse(&bsName, false, true);
  1741. if(FAILED(sc))
  1742. return sc;
  1743. CSysFreeMe fm(bsName);
  1744. DWORD dwSizeNeeded = wcslen(bsName)+1;
  1745. DWORD dwBuffSize = *puNameBufLength;
  1746. *puNameBufLength = dwSizeNeeded;
  1747. if(pName)
  1748. {
  1749. if(dwSizeNeeded > dwBuffSize)
  1750. return WBEM_E_BUFFER_TOO_SMALL;
  1751. StringCchCopyW(pName,dwSizeNeeded, bsName);
  1752. }
  1753. return S_OK;
  1754. }
  1755. /*++
  1756. Routine Description:
  1757. Removes a namespace.
  1758. Arguments:
  1759. uIndex - 0 based index of namespace to be removed. 0 is the leftmost.
  1760. Return Value:
  1761. S_OK if all is well, else an error code.
  1762. --*/
  1763. HRESULT CDefPathParser::RemoveNamespaceAt(
  1764. /* [in] */ ULONG uIndex)
  1765. {
  1766. CSafeInCritSec cs(m_pCS->GetCS());
  1767. if(!cs.IsOK())
  1768. return WBEM_E_OUT_OF_MEMORY;
  1769. DWORD dwNSCnt;
  1770. GetNamespaceCount(&dwNSCnt);
  1771. // check the parameter, index must be between 0 and count-1!
  1772. if(uIndex >= dwNSCnt)
  1773. return WBEM_E_INVALID_PARAMETER;
  1774. // all is well, delete this
  1775. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1776. delete pTemp;
  1777. m_Components.RemoveAt(uIndex);
  1778. return S_OK;
  1779. }
  1780. /*++
  1781. Routine Description:
  1782. Removes all namespaces.
  1783. S_OK if all is well, else an error code.
  1784. --*/
  1785. HRESULT CDefPathParser::RemoveAllNamespaces()
  1786. {
  1787. CSafeInCritSec cs(m_pCS->GetCS());
  1788. if(!cs.IsOK())
  1789. return WBEM_E_OUT_OF_MEMORY;
  1790. DWORD dwNum = GetNumNamespaces();
  1791. for (DWORD dwIx = 0; dwIx < dwNum; dwIx++)
  1792. {
  1793. CParsedComponent * pNS = (CParsedComponent *)m_Components[0];
  1794. delete pNS;
  1795. m_Components.RemoveAt(0);
  1796. }
  1797. return S_OK;
  1798. }
  1799. /*++
  1800. Routine Description:
  1801. Gets the number of scopes
  1802. Arguments:
  1803. puCount - where the number is set.
  1804. Return Value:
  1805. S_OK if all is well, else an error code.
  1806. --*/
  1807. HRESULT CDefPathParser::GetScopeCount(/* [out] */ ULONG __RPC_FAR *puCount)
  1808. {
  1809. CSafeInCritSec cs(m_pCS->GetCS());
  1810. if(!cs.IsOK())
  1811. return WBEM_E_OUT_OF_MEMORY;
  1812. if(puCount == NULL)
  1813. return WBEM_E_INVALID_PARAMETER;
  1814. *puCount = m_Components.Size() - GetNumNamespaces();
  1815. return S_OK;
  1816. }
  1817. /*++
  1818. Routine Description:
  1819. Inserts a scope into the path. An index of 0 inserts it
  1820. at the front of the list. The maximum allowed value is equal
  1821. to the current number of scope which results in adding it
  1822. to the end of the list.
  1823. Arguments:
  1824. uIndex - See description
  1825. pszClass - Name of the new scope
  1826. Return Value:
  1827. S_OK if all is well, else an error code.
  1828. --*/
  1829. HRESULT CDefPathParser::SetScope(
  1830. /* [in] */ ULONG uIndex,
  1831. /* [in] */ LPWSTR pszClass)
  1832. {
  1833. CSafeInCritSec cs(m_pCS->GetCS());
  1834. if(!cs.IsOK())
  1835. return WBEM_E_OUT_OF_MEMORY;
  1836. DWORD dwScopeCnt = m_Components.Size();
  1837. uIndex += GetNumNamespaces();
  1838. if(pszClass == NULL || uIndex > dwScopeCnt)
  1839. return WBEM_E_INVALID_PARAMETER;
  1840. CParsedComponent *pNew = new CParsedComponent(m_pCS);
  1841. if(pNew == NULL)
  1842. return WBEM_E_OUT_OF_MEMORY;
  1843. pNew->m_sClassName = SysAllocString(pszClass);
  1844. if(pNew->m_sClassName == NULL)
  1845. {
  1846. delete pNew;
  1847. return WBEM_E_OUT_OF_MEMORY;
  1848. }
  1849. int iRet = m_Components.InsertAt(uIndex, pNew);
  1850. if(iRet == CFlexArray::no_error)
  1851. return S_OK;
  1852. else
  1853. {
  1854. delete pNew;
  1855. return WBEM_E_OUT_OF_MEMORY;
  1856. }
  1857. return S_OK;
  1858. }
  1859. HRESULT CDefPathParser::SetScopeFromText(
  1860. /* [in] */ ULONG uIndex,
  1861. /* [in] */ LPWSTR pszText)
  1862. {
  1863. return WBEM_E_NOT_AVAILABLE;
  1864. }
  1865. /*++
  1866. Routine Description:
  1867. Retrieves scope information.
  1868. Arguments:
  1869. uIndex - 0 based index. 0 is the leftmost scope
  1870. uClassNameBufSize - size of pszClass in WCHAR
  1871. pszClass - Optional, caller supplied buffer where name is to be copied
  1872. pKeyList - Optional, returns a pKeyList pointer. Caller must call Release.
  1873. Return Value:
  1874. S_OK if all is well, else an error code.
  1875. --*/
  1876. HRESULT CDefPathParser::GetScope(
  1877. /* [in] */ ULONG uIndex,
  1878. /* [in] */ ULONG * puClassNameBufSize,
  1879. /* [in] */ LPWSTR pszClass,
  1880. /* [out] */ IWbemPathKeyList __RPC_FAR *__RPC_FAR *pKeyList)
  1881. {
  1882. CSafeInCritSec cs(m_pCS->GetCS());
  1883. if(!cs.IsOK())
  1884. return WBEM_E_OUT_OF_MEMORY;
  1885. DWORD dwScopeCnt = m_Components.Size();
  1886. HRESULT hr = S_OK;
  1887. uIndex += GetNumNamespaces();
  1888. if(uIndex >= dwScopeCnt)
  1889. return WBEM_E_INVALID_PARAMETER;
  1890. if(puClassNameBufSize && (*puClassNameBufSize > 0 && pszClass == NULL))
  1891. return WBEM_E_INVALID_PARAMETER;
  1892. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1893. if(puClassNameBufSize)
  1894. {
  1895. BSTR bsName;
  1896. SCODE sc = pTemp->GetName(&bsName);
  1897. if(FAILED(sc))
  1898. {
  1899. return sc;
  1900. }
  1901. CSysFreeMe fm(bsName);
  1902. DWORD dwSizeNeeded = wcslen(bsName)+1;
  1903. DWORD dwBuffSize = *puClassNameBufSize;
  1904. *puClassNameBufSize = dwSizeNeeded;
  1905. if(pszClass)
  1906. {
  1907. if(dwSizeNeeded > dwBuffSize)
  1908. return WBEM_E_BUFFER_TOO_SMALL;
  1909. StringCchCopyW(pszClass,dwSizeNeeded, bsName);
  1910. }
  1911. }
  1912. if(pKeyList)
  1913. {
  1914. hr = pTemp->QueryInterface(IID_IWbemPathKeyList, (void **)pKeyList);
  1915. if(FAILED(hr))
  1916. return hr;
  1917. }
  1918. return S_OK;
  1919. }
  1920. HRESULT CDefPathParser::GetScopeAsText(
  1921. /* [in] */ ULONG uIndex,
  1922. /* [out][in] */ ULONG __RPC_FAR *puTextBufSize,
  1923. /* [out][in] */ LPWSTR pszText)
  1924. {
  1925. CSafeInCritSec cs(m_pCS->GetCS());
  1926. if(!cs.IsOK())
  1927. return WBEM_E_OUT_OF_MEMORY;
  1928. DWORD dwScopeCnt = m_Components.Size();
  1929. uIndex += GetNumNamespaces();
  1930. if(uIndex >= dwScopeCnt || puTextBufSize == NULL)
  1931. return WBEM_E_INVALID_PARAMETER;
  1932. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1933. BSTR bstr;
  1934. HRESULT hr = pTemp->Unparse(&bstr, true, true);
  1935. if(FAILED(hr))
  1936. return hr;
  1937. CSysFreeMe fm(bstr);
  1938. DWORD dwBuffSize = *puTextBufSize;
  1939. DWORD dwSizeNeeded = wcslen(bstr)+1;
  1940. *puTextBufSize = dwSizeNeeded;
  1941. if(pszText)
  1942. {
  1943. if(dwSizeNeeded > dwBuffSize)
  1944. return WBEM_E_BUFFER_TOO_SMALL;
  1945. StringCchCopyW(pszText,dwSizeNeeded, bstr);
  1946. }
  1947. return S_OK;
  1948. }
  1949. /*++
  1950. Routine Description:
  1951. Removes a scope.
  1952. Arguments:
  1953. uIndex - 0 based index. 0 is the leftmost scope.
  1954. Return Value:
  1955. S_OK if all is well, else an error code.
  1956. --*/
  1957. HRESULT CDefPathParser::RemoveScope(/* [in] */ ULONG uIndex)
  1958. {
  1959. HRESULT hr = S_OK;
  1960. CSafeInCritSec cs(m_pCS->GetCS());
  1961. if(!cs.IsOK())
  1962. return WBEM_E_OUT_OF_MEMORY;
  1963. bool bGotInterface = false;
  1964. uIndex += GetNumNamespaces();
  1965. if(uIndex >= (DWORD)m_Components.Size())
  1966. return WBEM_E_INVALID_PARAMETER;
  1967. CParsedComponent *pTemp = (CParsedComponent *)m_Components[uIndex];
  1968. pTemp->Release();
  1969. m_Components.RemoveAt(uIndex);
  1970. return S_OK;
  1971. }
  1972. /*++
  1973. Routine Description:
  1974. Removes all scopes.
  1975. Return Value:
  1976. S_OK if all is well, else an error code.
  1977. --*/
  1978. HRESULT CDefPathParser::RemoveAllScopes( void)
  1979. {
  1980. CSafeInCritSec cs(m_pCS->GetCS());
  1981. if(!cs.IsOK())
  1982. return WBEM_E_OUT_OF_MEMORY;
  1983. DWORD dwNumNS = GetNumNamespaces();
  1984. for (DWORD dwIx = dwNumNS; dwIx < (DWORD)m_Components.Size(); dwIx++)
  1985. {
  1986. CParsedComponent * pCom = (CParsedComponent *)m_Components[dwNumNS];
  1987. pCom->Release();
  1988. m_Components.RemoveAt(dwNumNS);
  1989. }
  1990. return S_OK;
  1991. }
  1992. /*++
  1993. Routine Description:
  1994. Sets the class name.
  1995. Arguments:
  1996. Name - New class name.
  1997. Return Value:
  1998. S_OK if all is well, else an error code.
  1999. --*/
  2000. HRESULT CDefPathParser::SetClassName(
  2001. /* [string][in] */ LPCWSTR Name)
  2002. {
  2003. CSafeInCritSec cs(m_pCS->GetCS());
  2004. if(!cs.IsOK())
  2005. return WBEM_E_OUT_OF_MEMORY;
  2006. if(Name == NULL)
  2007. return WBEM_E_INVALID_PARAMETER;
  2008. HRESULT hRes = WBEM_E_INVALID_OBJECT_PATH;
  2009. CParsedComponent * pClass = GetClass();
  2010. if (pClass)
  2011. {
  2012. if(pClass->m_sClassName)
  2013. SysFreeString(pClass->m_sClassName);
  2014. pClass->m_sClassName = NULL;
  2015. pClass->m_sClassName = SysAllocString(Name);
  2016. if(pClass->m_sClassName)
  2017. hRes = S_OK;
  2018. else
  2019. hRes = WBEM_E_OUT_OF_MEMORY;
  2020. }
  2021. else
  2022. hRes = CreateClassPart(0, Name);
  2023. return hRes;
  2024. }
  2025. /*++
  2026. Routine Description:
  2027. Gets the class name.
  2028. Arguments:
  2029. uBuffLength - size of pszName in WCHAR
  2030. pszName - caller supplied buffer where name is to be copied
  2031. Return Value:
  2032. S_OK if all is well, else an error code.
  2033. --*/
  2034. HRESULT CDefPathParser::GetClassName(
  2035. /* [in, out] */ ULONG * puBuffLength,
  2036. /* [string][out] */ LPWSTR pszName)
  2037. {
  2038. CSafeInCritSec cs(m_pCS->GetCS());
  2039. if(!cs.IsOK())
  2040. return WBEM_E_OUT_OF_MEMORY;
  2041. if(puBuffLength == NULL || (*puBuffLength > 0 && pszName == NULL))
  2042. return WBEM_E_INVALID_PARAMETER;
  2043. HRESULT hRes = WBEM_E_INVALID_OBJECT_PATH;
  2044. CParsedComponent * pClass = GetClass();
  2045. if (pClass && pClass->m_sClassName)
  2046. {
  2047. DWORD dwSizeNeeded = wcslen(pClass->m_sClassName) +1;
  2048. DWORD dwBuffSize = *puBuffLength;
  2049. *puBuffLength = dwSizeNeeded;
  2050. if(pszName)
  2051. {
  2052. if(dwSizeNeeded > dwBuffSize)
  2053. return WBEM_E_BUFFER_TOO_SMALL;
  2054. StringCchCopyW(pszName,dwSizeNeeded, pClass->m_sClassName);
  2055. }
  2056. hRes = S_OK;
  2057. }
  2058. return hRes;
  2059. }
  2060. /*++
  2061. Routine Description:
  2062. Gets the key list pointer for the class key list.
  2063. Arguments:
  2064. pOut - Set to the key list. Caller must call Release on this.
  2065. Return Value:
  2066. S_OK if all is well, else an error code.
  2067. --*/
  2068. HRESULT CDefPathParser::GetKeyList(
  2069. /* [out] */ IWbemPathKeyList __RPC_FAR *__RPC_FAR *pOut)
  2070. {
  2071. CSafeInCritSec cs(m_pCS->GetCS());
  2072. if(!cs.IsOK())
  2073. return WBEM_E_OUT_OF_MEMORY;
  2074. HRESULT hRes = WBEM_E_NOT_AVAILABLE;
  2075. CParsedComponent * pClass = GetClass();
  2076. if(pOut == NULL || pClass == NULL)
  2077. return WBEM_E_INVALID_PARAMETER;
  2078. hRes = pClass->QueryInterface(IID_IWbemPathKeyList, (void **)pOut);
  2079. return hRes;
  2080. }
  2081. /*++
  2082. Routine Description:
  2083. Creates a class part of one does not exist.
  2084. Arguments:
  2085. lFlags - not used for now, set to 0
  2086. Name - name of the class
  2087. Return Value:
  2088. S_OK if all is well, else an error code.
  2089. --*/
  2090. HRESULT CDefPathParser::CreateClassPart(
  2091. /* [in] */ long lFlags,
  2092. /* [string][in] */ LPCWSTR Name)
  2093. {
  2094. CSafeInCritSec cs(m_pCS->GetCS());
  2095. if(!cs.IsOK())
  2096. return WBEM_E_OUT_OF_MEMORY;
  2097. if(lFlags != 0 || Name == NULL)
  2098. return WBEM_E_INVALID_PARAMETER;
  2099. CParsedComponent * pClass = new CParsedComponent(m_pCS);
  2100. if(pClass == NULL)
  2101. return WBEM_E_OUT_OF_MEMORY;
  2102. pClass->m_sClassName = SysAllocString(Name);
  2103. if(pClass->m_sClassName == NULL)
  2104. {
  2105. delete pClass;
  2106. return WBEM_E_OUT_OF_MEMORY;
  2107. }
  2108. m_Components.Add(pClass);
  2109. return S_OK;
  2110. }
  2111. /*++
  2112. Routine Description:
  2113. Deletes the class part.
  2114. Arguments:
  2115. lFlags - Not used for now, set to 0
  2116. Return Value:
  2117. S_OK if all is well, else an error code.
  2118. --*/
  2119. HRESULT CDefPathParser::DeleteClassPart(
  2120. /* [in] */ long lFlags)
  2121. {
  2122. CSafeInCritSec cs(m_pCS->GetCS());
  2123. if(!cs.IsOK())
  2124. return WBEM_E_OUT_OF_MEMORY;
  2125. CParsedComponent * pClass = GetClass();
  2126. if(lFlags != 0)
  2127. return WBEM_E_INVALID_PARAMETER;
  2128. if(pClass == NULL)
  2129. return WBEM_E_NOT_FOUND;
  2130. pClass->Release();
  2131. int iSize = m_Components.Size();
  2132. m_Components.RemoveAt(iSize-1);
  2133. return S_OK;
  2134. }
  2135. /*++
  2136. Routine Description:
  2137. Does the actual work of the "Relative" tests.
  2138. Arguments:
  2139. wszMachine - Local machine name
  2140. wszNamespace - Namespace
  2141. bChildreOK - If true, then it is OK if the obj
  2142. path has additional child namespaces
  2143. Return Value:
  2144. TRUE if relative, else false
  2145. --*/
  2146. BOOL CDefPathParser::ActualRelativeTest(
  2147. /* [string][in] */ LPWSTR wszMachine,
  2148. /* [string][in] */ LPWSTR wszNamespace,
  2149. BOOL bChildrenOK)
  2150. {
  2151. CSafeInCritSec cs(m_pCS->GetCS());
  2152. if(!cs.IsOK())
  2153. return WBEM_E_OUT_OF_MEMORY;
  2154. if(!IsLocal(wszMachine))
  2155. return FALSE;
  2156. DWORD dwNumNamespaces = GetNumNamespaces();
  2157. if(dwNumNamespaces == 0)
  2158. return TRUE;
  2159. size_t cchTmp = wcslen(wszNamespace) + 1;
  2160. LPWSTR wszCopy = new wchar_t[cchTmp];
  2161. if(wszCopy == NULL)return FALSE;
  2162. StringCchCopyW(wszCopy,cchTmp, wszNamespace);
  2163. LPWSTR wszLeft = wszCopy;
  2164. WCHAR * pToFar = wszCopy + wcslen(wszCopy);
  2165. BOOL bFailed = FALSE;
  2166. for(DWORD i = 0; i < dwNumNamespaces; i++)
  2167. {
  2168. CParsedComponent * pInst = (CParsedComponent *)m_Components[i];
  2169. if(pInst == NULL)
  2170. {
  2171. bFailed = TRUE;
  2172. break;
  2173. }
  2174. BSTR bsNS = NULL;
  2175. HRESULT hr = pInst->Unparse(&bsNS, false, true);
  2176. if(FAILED(hr) || bsNS == NULL)
  2177. {
  2178. bFailed = TRUE;
  2179. break;
  2180. }
  2181. CSysFreeMe fm(bsNS);
  2182. if(bChildrenOK && wszLeft >= pToFar)
  2183. return TRUE;
  2184. unsigned int nLen = wcslen(bsNS);
  2185. if(nLen > wcslen(wszLeft))
  2186. {
  2187. bFailed = TRUE;
  2188. break;
  2189. }
  2190. if(i == dwNumNamespaces - 1 && wszLeft[nLen] != 0)
  2191. {
  2192. bFailed = TRUE;
  2193. break;
  2194. }
  2195. if(i != dwNumNamespaces - 1 && wszLeft[nLen] != L'\\' && bChildrenOK == FALSE)
  2196. {
  2197. bFailed = TRUE;
  2198. break;
  2199. }
  2200. wszLeft[nLen] = 0;
  2201. if(wbem_wcsicmp(wszLeft, bsNS))
  2202. {
  2203. bFailed = TRUE;
  2204. break;
  2205. }
  2206. wszLeft += nLen+1;
  2207. }
  2208. delete [] wszCopy;
  2209. return !bFailed;
  2210. }
  2211. /*++
  2212. Routine Description:
  2213. Tests if path is relative to the machine and namespace.
  2214. Arguments:
  2215. wszMachine - Local machine name
  2216. wszNamespace - Namespace
  2217. Return Value:
  2218. TRUE if relative, else false
  2219. --*/
  2220. BOOL CDefPathParser::IsRelative(
  2221. /* [string][in] */ LPWSTR wszMachine,
  2222. /* [string][in] */ LPWSTR wszNamespace)
  2223. {
  2224. return ActualRelativeTest(wszMachine, wszNamespace, FALSE);
  2225. }
  2226. /*++
  2227. Routine Description:
  2228. Tests if path is relative to the machine and namespace.
  2229. Arguments:
  2230. wszMachine - Local machine name
  2231. wszNamespace - Namespace
  2232. lFlags - flags, not used for now.
  2233. Return Value:
  2234. TRUE if relative, or a child namespace. else false
  2235. --*/
  2236. BOOL CDefPathParser::IsRelativeOrChild(
  2237. /* [string][in] */ LPWSTR wszMachine,
  2238. /* [string][in] */ LPWSTR wszNamespace,
  2239. /* [in] */ long lFlags)
  2240. {
  2241. if(lFlags != 0)
  2242. return FALSE;
  2243. return ActualRelativeTest(wszMachine, wszNamespace, TRUE);
  2244. }
  2245. /*++
  2246. Routine Description:
  2247. Tests if path is to local machine
  2248. Arguments:
  2249. wszMachine - Local machine name
  2250. Return Value:
  2251. TRUE if local, else false
  2252. --*/
  2253. BOOL CDefPathParser::IsLocal(
  2254. /* [string][in] */ LPCWSTR wszMachine)
  2255. {
  2256. CSafeInCritSec cs(m_pCS->GetCS());
  2257. if(!cs.IsOK())
  2258. return WBEM_E_OUT_OF_MEMORY;
  2259. return (m_pServer == NULL || !wbem_wcsicmp(m_pServer, L".") ||
  2260. !wbem_wcsicmp(m_pServer, wszMachine));
  2261. }
  2262. /*++
  2263. Routine Description:
  2264. Tests if class name matches test
  2265. Arguments:
  2266. wszClassName - Local machine name
  2267. Return Value:
  2268. TRUE if local, else false
  2269. --*/
  2270. BOOL CDefPathParser::IsSameClassName(
  2271. /* [string][in] */ LPCWSTR wszClass)
  2272. {
  2273. CSafeInCritSec cs(m_pCS->GetCS());
  2274. if(!cs.IsOK())
  2275. return WBEM_E_OUT_OF_MEMORY;
  2276. CParsedComponent * pClass = GetClass();
  2277. if (pClass == NULL || pClass->m_sClassName == NULL || wszClass == NULL)
  2278. return FALSE;
  2279. return !wbem_wcsicmp(pClass->m_sClassName, wszClass);
  2280. }
  2281. /*++
  2282. Routine Description:
  2283. Returns just the namspace part of the path
  2284. Return Value:
  2285. pointer to the result. Null if failer. Caller should free.
  2286. --*/
  2287. LPWSTR CDefPathParser::GetNamespacePart()
  2288. {
  2289. LPWSTR lpRet = NULL;
  2290. lpRet = GetPath(0, GetNumNamespaces());
  2291. return lpRet;
  2292. }
  2293. /*++
  2294. Routine Description:
  2295. Returns the parent namespace part.
  2296. Return Value:
  2297. pointer to the result. Null if failer. Caller should free.
  2298. --*/
  2299. LPWSTR CDefPathParser::GetParentNamespacePart()
  2300. {
  2301. DWORD dwNumNS = GetNumNamespaces();
  2302. if (dwNumNS < 2)
  2303. return NULL;
  2304. LPWSTR lpRet = NULL;
  2305. lpRet = GetPath(0, dwNumNS-1);
  2306. return lpRet;
  2307. }
  2308. long CDefPathParser::GetNumNamespaces()
  2309. {
  2310. long lRet = 0;
  2311. for(DWORD dwCnt = 0; dwCnt < (DWORD)m_Components.Size(); dwCnt++)
  2312. {
  2313. CParsedComponent * pInst = (CParsedComponent *)m_Components[dwCnt];
  2314. if(pInst->IsPossibleNamespace())
  2315. lRet++;
  2316. else
  2317. break;
  2318. }
  2319. return lRet;
  2320. }
  2321. /*++
  2322. Routine Description:
  2323. Sorts the keys based on the key name
  2324. Return Value:
  2325. TRUE if OK.
  2326. --*/
  2327. BOOL CDefPathParser::SortKeys()
  2328. {
  2329. // Sort the key refs lexically. If there is only
  2330. // one key, there is nothing to sort anyway.
  2331. // =============================================
  2332. BOOL bChanges = FALSE;
  2333. if (m_Components.Size())
  2334. {
  2335. CParsedComponent *pComp = GetLastComponent();
  2336. if (pComp)
  2337. {
  2338. CParsedComponent *pInst = (CParsedComponent *)pComp;
  2339. if (pInst->m_Keys.Size() > 1)
  2340. {
  2341. while (bChanges)
  2342. {
  2343. bChanges = FALSE;
  2344. for (DWORD dwIx = 0; dwIx < (DWORD)pInst->m_Keys.Size() - 1; dwIx++)
  2345. {
  2346. CKeyRef * pFirst = (CKeyRef *)pInst->m_Keys[dwIx];
  2347. CKeyRef * pSecond = (CKeyRef *)pInst->m_Keys[dwIx+1];
  2348. if (wbem_wcsicmp(pFirst->m_pName, pSecond->m_pName) > 0)
  2349. {
  2350. pInst->m_Keys.SetAt(dwIx, pSecond);
  2351. pInst->m_Keys.SetAt(dwIx+1, pFirst);
  2352. bChanges = TRUE;
  2353. }
  2354. }
  2355. }
  2356. }
  2357. }
  2358. }
  2359. return bChanges;
  2360. }
  2361. HRESULT CDefPathParser::AddComponent(CParsedComponent * pComp)
  2362. {
  2363. if (CFlexArray::no_error == m_Components.Add(pComp))
  2364. return S_OK;
  2365. else
  2366. return WBEM_E_OUT_OF_MEMORY;
  2367. }