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.

3481 lines
96 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
  4. //
  5. // repcache.cpp
  6. //
  7. // cvadai 19-Mar-99 Created as prototype for Quasar.
  8. //
  9. //***************************************************************************
  10. #define _REPDRVR_CPP_
  11. #pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the
  12. #pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
  13. #define _WIN32_DCOM
  14. #include "precomp.h"
  15. #include <repcache.h>
  16. #include <wbemint.h>
  17. #include <repdrvr.h>
  18. #include <objbase.h>
  19. #include <reputils.h>
  20. #include <crc64.h>
  21. #include <smrtptr.h>
  22. typedef std::map<SQL_ID, bool> SQL_IDMap;
  23. typedef std::map<SQL_ID, ULONG> SQLRefCountMap;
  24. typedef std::map <SQL_ID, ClassData *> ClassCache;
  25. typedef std::map <DWORD, DWORD> Properties;
  26. typedef std::vector <SQL_ID> SQLIDs;
  27. typedef std::map <_bstr_t, SQL_ID, _bstr_tNoCase> ClassNames;
  28. #define MAX_WIDTH_SCHEMANAME 127 // Smallest property name for Jet / SQL
  29. //***************************************************************************
  30. //
  31. // CObjectCache::CObjectCache
  32. //
  33. //***************************************************************************
  34. CObjectCache::CObjectCache()
  35. {
  36. m_dwMaxSize = 262140;
  37. InitializeCriticalSection(&m_cs);
  38. m_dwUsed = 0;
  39. }
  40. //***************************************************************************
  41. //
  42. // CObjectCache::~CObjectCache
  43. //
  44. //***************************************************************************
  45. CObjectCache::~CObjectCache()
  46. {
  47. EmptyCache();
  48. DeleteCriticalSection(&m_cs);
  49. }
  50. //***************************************************************************
  51. //
  52. // CObjectCache::EmptyCache
  53. //
  54. //***************************************************************************
  55. void CObjectCache::EmptyCache()
  56. {
  57. _WMILockit lkt(&m_cs);
  58. m_ObjCache.Empty();
  59. m_dwUsed = 0;
  60. }
  61. //***************************************************************************
  62. //
  63. // CObjectCache::GetObject
  64. //
  65. //***************************************************************************
  66. HRESULT CObjectCache::GetObject (LPCWSTR lpPath, IWbemClassObject **ppObj,
  67. SQL_ID *dScopeId)
  68. {
  69. HRESULT hr = WBEM_S_NO_ERROR;
  70. _WMILockit lkt(&m_cs);
  71. DWORD dwLock = 0;
  72. SQL_ID dwID = 0;
  73. dwID = CRC64::GenerateHashValue(lpPath);
  74. hr = GetObject (dwID, ppObj, dScopeId);
  75. return hr;
  76. }
  77. //***************************************************************************
  78. //
  79. // CObjectCache::GetObject
  80. //
  81. //***************************************************************************
  82. HRESULT CObjectCache::GetObject (SQL_ID dObjectId, IWbemClassObject **ppObj,
  83. SQL_ID *dScopeId)
  84. {
  85. HRESULT hr = WBEM_S_NO_ERROR;
  86. _WMILockit lkt(&m_cs);
  87. CacheInfo *pObj = NULL;
  88. hr = m_ObjCache.Get(dObjectId, &pObj);
  89. if (pObj)
  90. {
  91. pObj->m_tLastAccess = time(0);
  92. if (ppObj)
  93. {
  94. hr = pObj->m_pObj->Clone(ppObj);
  95. }
  96. if (dScopeId)
  97. *dScopeId = pObj->m_dScopeId;
  98. }
  99. else
  100. hr = WBEM_E_NOT_FOUND;
  101. return hr;
  102. }
  103. //***************************************************************************
  104. //
  105. // CObjectCache::GetObjectId
  106. //
  107. //***************************************************************************
  108. HRESULT CObjectCache::GetObjectId (LPCWSTR lpPath, SQL_ID &dObjId, SQL_ID &dClassId, SQL_ID *dScopeId)
  109. {
  110. HRESULT hr = WBEM_S_NO_ERROR;
  111. _WMILockit lkt(&m_cs);
  112. if (lpPath == NULL)
  113. hr = WBEM_E_INVALID_PARAMETER;
  114. else
  115. {
  116. dObjId = CRC64::GenerateHashValue(lpPath);
  117. CacheInfo *pTemp = NULL;
  118. hr = m_ObjCache.Get(dObjId, &pTemp);
  119. if (SUCCEEDED(hr))
  120. {
  121. dClassId = pTemp->m_dClassId;
  122. if (dScopeId)
  123. *dScopeId = pTemp->m_dScopeId;
  124. }
  125. }
  126. return hr;
  127. }
  128. //***************************************************************************
  129. //
  130. // CObjectCache::PutObject
  131. //
  132. //***************************************************************************
  133. HRESULT CObjectCache::PutObject (SQL_ID dID, SQL_ID dClassId, SQL_ID dScopeId, LPCWSTR lpPath, bool bStrongCache, IWbemClassObject *_pObj)
  134. {
  135. // The cache can't exceed the maximum byte size.
  136. // and must set current used
  137. HRESULT hr = WBEM_S_NO_ERROR;
  138. _WMILockit lkt(&m_cs);
  139. bool bNew = false;
  140. if (!_pObj)
  141. return WBEM_E_INVALID_PARAMETER;
  142. IWbemClassObject *pObj = NULL;
  143. hr = _pObj->Clone(&pObj);
  144. if (FAILED(hr))
  145. return hr;
  146. // Don't cache security descriptor
  147. hr = pObj->Put(L"__SECURITY_DESCRIPTOR", 0, NULL, CIM_UINT8|CIM_FLAG_ARRAY);
  148. CacheInfo *pTemp = NULL;
  149. size_t NewSize;
  150. hr = m_ObjCache.Get(dID, &pTemp);
  151. if (FAILED(hr))
  152. {
  153. bNew = true;
  154. NewSize = GetSize(pObj) + sizeof(CacheInfo) + wcslen(lpPath);
  155. hr = WBEM_S_NO_ERROR;
  156. }
  157. else
  158. NewSize = (GetSize(pObj) - GetSize(pTemp->m_pObj));
  159. if ((NewSize + m_dwUsed) > m_dwMaxSize)
  160. hr = ResizeCache(NewSize, dID, bStrongCache);
  161. if (SUCCEEDED(hr) && NewSize)
  162. {
  163. if (pTemp)
  164. {
  165. IWbemClassObject *pTempObj = pTemp->m_pObj;
  166. if (pTempObj)
  167. pTempObj->Release();
  168. }
  169. else
  170. {
  171. pTemp = new CacheInfo;
  172. if (!pTemp)
  173. return WBEM_E_OUT_OF_MEMORY;
  174. pTemp->m_bStrong = bStrongCache;
  175. }
  176. pTemp->m_dObjectId = dID;
  177. pTemp->m_dClassId = dClassId;
  178. pTemp->m_dScopeId = dScopeId;
  179. pTemp->m_tLastAccess = time(0);
  180. delete pTemp->m_sPath;
  181. pTemp->m_sPath = Macro_CloneLPWSTR(lpPath);
  182. pTemp->m_pObj = pObj;
  183. pTemp->m_bStrong = ((int)pTemp->m_bStrong > (int)bStrongCache) ? pTemp->m_bStrong : bStrongCache; // Strong has precendence.
  184. if (bNew)
  185. {
  186. hr = m_ObjCache.Insert(dID, pTemp);
  187. }
  188. m_dwUsed += NewSize;
  189. }
  190. return hr;
  191. }
  192. //***************************************************************************
  193. //
  194. // CObjectCache::DeleteObject
  195. //
  196. //***************************************************************************
  197. HRESULT CObjectCache::DeleteObject (SQL_ID dID)
  198. {
  199. // Set current used
  200. // Recalculate the number of bytes used.
  201. HRESULT hr = WBEM_S_NO_ERROR;
  202. _WMILockit lkt(&m_cs);
  203. CacheInfo *pObj = NULL;
  204. hr = m_ObjCache.Get(dID, &pObj);
  205. if (SUCCEEDED(hr))
  206. {
  207. if (pObj->m_pObj)
  208. {
  209. m_dwUsed -= GetSize(pObj->m_pObj);
  210. // pObj->m_pObj->Release();
  211. }
  212. m_dwUsed -= sizeof(CacheInfo);
  213. m_dwUsed -= wcslen(pObj->m_sPath);
  214. hr = m_ObjCache.Delete(dID);
  215. }
  216. if (hr == WBEM_E_NOT_FOUND)
  217. hr = WBEM_S_NO_ERROR;
  218. return hr;
  219. }
  220. //***************************************************************************
  221. //
  222. // CObjectCache::ObjectExists
  223. //
  224. //***************************************************************************
  225. bool CObjectCache::ObjectExists (SQL_ID dObjectId)
  226. {
  227. return (m_ObjCache.Exists(dObjectId));
  228. }
  229. //***************************************************************************
  230. //
  231. // CObjectCache::SetCacheSize
  232. //
  233. //***************************************************************************
  234. HRESULT CObjectCache::SetCacheSize(const DWORD dwMaxSize)
  235. {
  236. HRESULT hr = WBEM_S_NO_ERROR;
  237. _WMILockit lkt(&m_cs);
  238. // Physically resize the cache.
  239. // If that works, set the variable
  240. if (dwMaxSize == 0)
  241. {
  242. _WMILockit lkt(&m_cs);
  243. EmptyCache();
  244. }
  245. else if (m_dwMaxSize > dwMaxSize)
  246. {
  247. DWORD dwDiff = m_dwMaxSize - dwMaxSize;
  248. hr = ResizeCache(dwDiff, 0);
  249. }
  250. if (SUCCEEDED(hr))
  251. m_dwMaxSize = dwMaxSize;
  252. return hr;
  253. }
  254. //***************************************************************************
  255. //
  256. // CObjectCache::GetCurrentUsage
  257. //
  258. //***************************************************************************
  259. HRESULT CObjectCache::GetCurrentUsage(DWORD &dwBytesUsed)
  260. {
  261. HRESULT hr = WBEM_S_NO_ERROR;
  262. _WMILockit lkt(&m_cs);
  263. dwBytesUsed = m_dwUsed;
  264. return hr;
  265. }
  266. //***************************************************************************
  267. //
  268. // CObjectCache::GetCacheSize
  269. //
  270. //***************************************************************************
  271. HRESULT CObjectCache::GetCacheSize(DWORD &dwSizeInBytes)
  272. {
  273. HRESULT hr = WBEM_S_NO_ERROR;
  274. _WMILockit lkt(&m_cs);
  275. dwSizeInBytes = m_dwMaxSize;
  276. return hr;
  277. }
  278. //***************************************************************************
  279. //
  280. // CObjectCache::FindFirst
  281. //
  282. //***************************************************************************
  283. HRESULT CObjectCache::FindFirst(SQL_ID &dObjectId, SQL_ID &dClassId, SQL_ID *dScopeId)
  284. {
  285. HRESULT hr = WBEM_S_NO_ERROR;
  286. _WMILockit lkt(&m_cs);
  287. CListElement *pTemp = NULL;
  288. pTemp = m_ObjCache.FindFirst();
  289. if (pTemp != NULL)
  290. {
  291. CacheInfo *pTmp = (CacheInfo *)pTemp->m_pObj;
  292. pTmp->m_tLastAccess = time(0);
  293. dObjectId = pTmp->m_dObjectId;
  294. dClassId = pTmp->m_dClassId;
  295. if (dScopeId)
  296. *dScopeId = pTmp->m_dScopeId;
  297. delete pTemp;
  298. }
  299. else
  300. hr = WBEM_E_NOT_FOUND;
  301. return hr;
  302. }
  303. //***************************************************************************
  304. //
  305. // CObjectCache::FindNext
  306. //
  307. //***************************************************************************
  308. HRESULT CObjectCache::FindNext (SQL_ID dLastId, SQL_ID &dObjectId, SQL_ID &dClassId, SQL_ID *dScopeId)
  309. {
  310. HRESULT hr = WBEM_S_NO_ERROR;
  311. _WMILockit lkt(&m_cs);
  312. CListElement *pTemp = NULL;
  313. pTemp = m_ObjCache.FindNext(dLastId);
  314. if (pTemp != NULL)
  315. {
  316. CacheInfo *pTmp = (CacheInfo *)pTemp->m_pObj;
  317. pTmp->m_tLastAccess = time(0);
  318. dObjectId = pTmp->m_dObjectId;
  319. dClassId = pTmp->m_dClassId;
  320. if (dScopeId)
  321. *dScopeId = pTmp->m_dScopeId;
  322. delete pTemp;
  323. }
  324. else
  325. hr = WBEM_E_NOT_FOUND;
  326. return hr;
  327. }
  328. //***************************************************************************
  329. //
  330. // CObjectCache::GetSize
  331. //
  332. //***************************************************************************
  333. DWORD CObjectCache::GetSize(IWbemClassObject *pObj)
  334. {
  335. DWORD dwRet = 0;
  336. _IWmiObject *pInt = NULL;
  337. HRESULT hr = 0;
  338. hr = pObj->QueryInterface(IID__IWmiObject, (void **)&pInt);
  339. CReleaseMe rInt (pInt);
  340. if (SUCCEEDED(hr))
  341. {
  342. /* No idea how big this can be. Is there a better way to do this?*/
  343. DWORD dwSize = 0;
  344. pInt->GetObjectMemory(NULL, dwSize, &dwRet);
  345. }
  346. return dwRet;
  347. }
  348. //***************************************************************************
  349. //
  350. // CObjectCache::ResizeCache
  351. //
  352. //***************************************************************************
  353. HRESULT CObjectCache::ResizeCache(DWORD dwReqBytes, SQL_ID dLeave, bool bForce)
  354. {
  355. HRESULT hr = WBEM_S_NO_ERROR;
  356. // Try to free up dwReqBytes, starting with
  357. // the oldest weakly cached objects.
  358. // ========================================
  359. while ((dwReqBytes + m_dwUsed) > m_dwMaxSize)
  360. {
  361. hr = WBEM_E_BUFFER_TOO_SMALL;
  362. CListElement *pTemp = NULL;
  363. pTemp = m_ObjCache.FindFirst();
  364. while (pTemp != NULL)
  365. {
  366. SQL_ID dID = pTemp->m_dId;
  367. if (dID && dID != dLeave)
  368. {
  369. CacheInfo *pTmp = (CacheInfo *)pTemp->m_pObj;
  370. if (!pTmp->m_bStrong)
  371. DeleteObject(dID);
  372. if ((dwReqBytes + m_dwUsed) <= m_dwMaxSize)
  373. {
  374. hr = WBEM_S_NO_ERROR;
  375. break;
  376. }
  377. }
  378. delete pTemp;
  379. pTemp = m_ObjCache.FindNext(dID);
  380. }
  381. if ((dwReqBytes + m_dwUsed) <= m_dwMaxSize)
  382. {
  383. hr = WBEM_S_NO_ERROR;
  384. break;
  385. }
  386. // Only remove other strong cached elements
  387. // if we have to.
  388. // =========================================
  389. if (bForce)
  390. {
  391. pTemp = m_ObjCache.FindFirst();
  392. while (pTemp != NULL)
  393. {
  394. SQL_ID dID = pTemp->m_dId;
  395. if (dID != dLeave)
  396. {
  397. DeleteObject(dID);
  398. if ((dwReqBytes + m_dwUsed) <= m_dwMaxSize)
  399. {
  400. hr = WBEM_S_NO_ERROR;
  401. break;
  402. }
  403. }
  404. pTemp = m_ObjCache.FindNext(dID);
  405. }
  406. }
  407. break; // if here, cache is empty.
  408. }
  409. return hr;
  410. }
  411. //***************************************************************************
  412. //
  413. // LockData::GetMaxLock
  414. //
  415. //***************************************************************************
  416. DWORD LockData::GetMaxLock(bool bImmediate, bool bSubScopeOnly)
  417. {
  418. DWORD dwRet = 0;
  419. for (int i = 0; i < m_List.size(); i++)
  420. {
  421. LockItem *pItem = m_List.at(i);
  422. if (pItem)
  423. {
  424. if (bImmediate && pItem->m_bLockOnChild)
  425. continue;
  426. if (bSubScopeOnly && !(pItem->m_dwHandleType & WMIDB_HANDLE_TYPE_SUBSCOPED))
  427. continue;
  428. dwRet = GetMaxBytes(pItem->m_dwHandleType, dwRet);
  429. }
  430. }
  431. return dwRet;
  432. }
  433. //***************************************************************************
  434. //
  435. // LockData::LockExists
  436. //
  437. //***************************************************************************
  438. bool LockData::LockExists (DWORD dwHandleType)
  439. {
  440. bool bRet = false;
  441. for (int i = 0; i < m_List.size(); i++)
  442. {
  443. LockItem *pItem = m_List.at(i);
  444. if (pItem)
  445. {
  446. if (!pItem->m_bLockOnChild)
  447. {
  448. if ((pItem->m_dwHandleType & dwHandleType) == dwHandleType)
  449. {
  450. bRet = true;
  451. break;
  452. }
  453. }
  454. }
  455. }
  456. return bRet;
  457. }
  458. //***************************************************************************
  459. //
  460. // CLockCache::~CLockCache
  461. //
  462. //***************************************************************************
  463. CLockCache::~CLockCache()
  464. {
  465. DeleteCriticalSection(&m_cs);
  466. }
  467. //***************************************************************************
  468. //
  469. // CLockCache::GetHandle
  470. //
  471. //***************************************************************************
  472. HRESULT CLockCache::GetHandle(SQL_ID ObjId, DWORD dwType, IWmiDbHandle **ppRet)
  473. {
  474. HRESULT hr = WBEM_S_NO_ERROR;
  475. _WMILockit lkt(&m_cs);
  476. *ppRet = NULL;
  477. LockData *temp = NULL;
  478. hr = m_Cache.Get(ObjId, &temp);
  479. if (SUCCEEDED(hr))
  480. {
  481. LockData *pData = (LockData *)temp;
  482. if (pData)
  483. {
  484. LockItem *pItem = NULL;
  485. for (int i = 0; i < pData->m_List.size(); i++)
  486. {
  487. pItem = pData->m_List.at(i);
  488. if (pItem->m_dwHandleType == dwType)
  489. {
  490. if (pItem->m_pObj)
  491. {
  492. pItem->m_pObj->AddRef();
  493. *ppRet = (IWmiDbHandle *)pItem->m_pObj;
  494. }
  495. break;
  496. }
  497. }
  498. }
  499. }
  500. return hr;
  501. }
  502. //***************************************************************************
  503. //
  504. // CLockCache::AddLock
  505. //
  506. //***************************************************************************
  507. HRESULT CLockCache::AddLock(bool bImmediate, SQL_ID ObjId, DWORD Type, IUnknown *pUnk, SQL_ID dNsId,
  508. SQL_ID dClassId, CSchemaCache *pCache, bool bChg, bool bChildLock, SQL_ID SourceId,
  509. DWORD *dwVersion)
  510. {
  511. HRESULT hr = WBEM_S_NO_ERROR;
  512. _WMILockit lkt(&m_cs);
  513. SQL_ID dParentId = 0;
  514. if (bChildLock)
  515. Type &= ~WMIDB_HANDLE_TYPE_AUTODELETE;
  516. if (Type & WMIDB_HANDLE_TYPE_AUTODELETE)
  517. {
  518. DWORD dwParentLock = 0;
  519. GetCurrentLock(dNsId, false, dwParentLock);
  520. if (!(dwParentLock & WMIDB_HANDLE_TYPE_AUTODELETE))
  521. {
  522. GetCurrentLock(dClassId, false, dwParentLock);
  523. if (!(dwParentLock & WMIDB_HANDLE_TYPE_AUTODELETE))
  524. {
  525. SQL_ID ClassId = dClassId, dParentId = 0;
  526. while (SUCCEEDED(pCache->GetParentId(ClassId, dParentId)))
  527. {
  528. GetCurrentLock(dParentId, false, dwParentLock);
  529. if (dwParentLock & WMIDB_HANDLE_TYPE_AUTODELETE)
  530. break;
  531. ClassId = dParentId;
  532. }
  533. }
  534. }
  535. if (dwParentLock & WMIDB_HANDLE_TYPE_AUTODELETE)
  536. return WBEM_E_INVALID_HANDLE_REQUEST;
  537. }
  538. // If this is a cookie, we really don't
  539. // care what locks exist, and we do
  540. // not need to add it to the list.
  541. // Unless its an auto-delete handle...
  542. // ======================================
  543. if ((Type & 0xF)== WMIDB_HANDLE_TYPE_COOKIE &&
  544. !(Type & WMIDB_HANDLE_TYPE_AUTODELETE))
  545. return WBEM_S_NO_ERROR;
  546. // If this is a class,
  547. // use its own ID as the Class ID.
  548. // ==============================
  549. if (dClassId == 1)
  550. dClassId = ObjId;
  551. LockData *temp = NULL;
  552. hr = m_Cache.Get(ObjId, &temp);
  553. LockData *pData = NULL;
  554. if (SUCCEEDED(hr))
  555. {
  556. pData = (LockData *)temp;
  557. }
  558. else
  559. {
  560. hr = WBEM_S_NO_ERROR;
  561. pData = new LockData;
  562. if (pData)
  563. {
  564. pData->m_dObjectId = ObjId;
  565. pData->m_dwStatus = 0; // Calculated at the end.
  566. pData->m_dwNumLocks = 0;
  567. pData->m_dwCompositeStatus = 0;
  568. pData->m_dwVersion = 1;
  569. pData->m_dwCompositeVersion = 1;
  570. m_Cache.Insert(ObjId, pData);
  571. // Load the owner list
  572. if (!bChildLock)
  573. {
  574. SQL_ID dParent = 0, dClass = 0;
  575. if (dClassId != 2)
  576. {
  577. pCache->GetParentNamespace(dNsId, dParent, &dClass);
  578. while (dParent) // Don't propogate locks across namespaces!
  579. {
  580. pData->m_OwnerIds[dParent];
  581. if (dClass == 2)
  582. break;
  583. pCache->GetParentNamespace(dParent, dParent, &dClass);
  584. }
  585. pData->m_OwnerIds[dNsId] = true;
  586. }
  587. if (dClassId != ObjId)
  588. pData->m_OwnerIds[dClassId] = true;
  589. while (SUCCEEDED(pCache->GetParentId(dClassId, dParentId)))
  590. {
  591. pData->m_OwnerIds[dParentId] = 1;
  592. dClassId = dParentId;
  593. }
  594. }
  595. }
  596. else
  597. hr = WBEM_E_OUT_OF_MEMORY;
  598. }
  599. if (SUCCEEDED(hr))
  600. {
  601. // Make sure the parent objects aren't directly locked.
  602. // ====================================================
  603. if (!CanLockHandle(ObjId, Type, bImmediate, false))
  604. hr = WBEM_E_ACCESS_DENIED;
  605. if (SUCCEEDED(hr))
  606. {
  607. SQL_IDMap::iterator item = pData->m_OwnerIds.begin();
  608. while (item != pData->m_OwnerIds.end())
  609. {
  610. if (!CanLockHandle((*item).first, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), true, true))
  611. {
  612. hr = WBEM_E_ACCESS_DENIED;
  613. break;
  614. }
  615. item++;
  616. }
  617. }
  618. // If all that worked, we can now attempt to
  619. // add the lock to this object.
  620. // =========================================
  621. if (SUCCEEDED(hr))
  622. {
  623. LockItem *pItem = NULL;
  624. // Now we need to see if this lock already exists
  625. // for this handle type.
  626. // ==============================================
  627. pItem = new LockItem;
  628. if (pItem)
  629. {
  630. pItem->m_dwHandleType = Type;
  631. pItem->m_pObj = pUnk;
  632. pItem->m_dSourceId = SourceId;
  633. pItem->m_dwVersion = pData->m_dwVersion;
  634. if (bChildLock)
  635. pItem->m_bLockOnChild = true;
  636. else
  637. pItem->m_bLockOnChild = false;
  638. // Attempt to lock all the parent objects.
  639. // Pass in zeroes for namespace and class Ids
  640. // so we don't recurse.
  641. if (dNsId && dClassId != 2)
  642. {
  643. hr = AddLock(true, dNsId, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, true, ObjId);
  644. if (SUCCEEDED(hr))
  645. {
  646. SQL_ID dParent = 0, dClass = 0;
  647. pCache->GetParentNamespace(dNsId, dParent, &dClass);
  648. while (dParent)
  649. {
  650. hr = AddLock(true, dParent, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, true, ObjId);
  651. // Don't propogate locks across namespaces.
  652. if (dClass == 2)
  653. break;
  654. pCache->GetParentNamespace(dParent, dParent, &dClass);
  655. }
  656. }
  657. }
  658. if (dClassId != 1 && dClassId != 0) // Disregard the __Class class
  659. {
  660. if (dClassId != ObjId) // We already saved this one.
  661. hr = AddLock(true, dClassId, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, true, ObjId);
  662. hr = pCache->GetParentId(dClassId, dParentId);
  663. while (SUCCEEDED(hr))
  664. {
  665. hr = AddLock(true, dParentId, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, true, ObjId);
  666. hr = pCache->GetParentId(dParentId, dParentId);
  667. }
  668. hr = WBEM_S_NO_ERROR;
  669. }
  670. // If this is a blocking handle, make sure
  671. // we lock out any existing handles on child
  672. // objects. If there any other locks on sub
  673. // components of this object, they should be
  674. // in the list at this point.
  675. // If this is a versioned handle, that needs
  676. // to be invalidated if there is an immediate
  677. // change to the parent object!!
  678. if (Type & WMIDB_HANDLE_TYPE_SUBSCOPED)
  679. {
  680. for (int i = 0; i < pData->m_List.size(); i++)
  681. {
  682. LockItem *pTemp = pData->m_List.at(i);
  683. if (pTemp && pTemp->m_dSourceId != 0)
  684. AddLock(true, pTemp->m_dSourceId, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, false, ObjId);
  685. }
  686. }
  687. // Only increment version type if this object changed,
  688. // or if there is an outstanding versioned|subscoped
  689. // handle type on this object and a child object chgd.
  690. // ====================================================
  691. if (bChg)
  692. {
  693. if (!bChildLock)
  694. {
  695. pData->m_dwVersion++;
  696. pData->m_dwCompositeVersion++;
  697. pItem->m_dwVersion = pData->m_dwVersion;
  698. }
  699. else if (bChildLock && pData->LockExists(WMIDB_HANDLE_TYPE_VERSIONED|WMIDB_HANDLE_TYPE_SUBSCOPED))
  700. pData->m_dwCompositeVersion++;
  701. }
  702. pData->m_List.push_back(pItem);
  703. pData->m_dwNumLocks++;
  704. // Update the lock type
  705. // ====================
  706. pData->m_dwStatus = pData->GetMaxLock(true);
  707. pData->m_dwCompositeStatus = pData->GetMaxLock(false);
  708. if (dwVersion)
  709. {
  710. if (bImmediate)
  711. *dwVersion = pData->m_dwVersion;
  712. else
  713. *dwVersion = pData->m_dwCompositeVersion;
  714. }
  715. }
  716. }
  717. }
  718. return hr;
  719. }
  720. //***************************************************************************
  721. //
  722. // CLockCache::DeleteLock
  723. //
  724. //***************************************************************************
  725. HRESULT CLockCache::DeleteLock(SQL_ID ObjId, bool bChildLock, DWORD HandleType, bool bDelChildren, void *pObj)
  726. {
  727. HRESULT hr = WBEM_S_NO_ERROR;
  728. _WMILockit lkt(&m_cs);
  729. // If this is the only lock,
  730. // remove the whole thing.
  731. // Otherwise just remove the item
  732. // Update the master lock
  733. // ==============================
  734. LockData *pData = NULL;
  735. LockData *temp = NULL;
  736. hr = m_Cache.Get(ObjId, &temp);
  737. if (SUCCEEDED(hr))
  738. {
  739. pData = (LockData *)temp;
  740. // If they specify a handle of zero,
  741. // we delete all entries for this ID.
  742. if (HandleType)
  743. {
  744. BOOL bFound = FALSE;
  745. LockItem *pItem = NULL;
  746. for (int i = 0; i < pData->m_List.size(); i++)
  747. {
  748. pItem = pData->m_List.at(i);
  749. if (pItem->m_dwHandleType == HandleType && (pItem->m_pObj == pObj))
  750. {
  751. if (bChildLock && !pItem->m_bLockOnChild)
  752. continue;
  753. if (pItem->m_pObj)
  754. ((CWmiDbHandle *)pItem->m_pObj)->m_dwHandleType = 0;
  755. delete pItem;
  756. pData->m_List.erase(&pData->m_List.at(i));
  757. pData->m_dwNumLocks--;
  758. bFound = TRUE;
  759. break;
  760. }
  761. }
  762. if (!pObj && !bFound)
  763. {
  764. for (int i = 0; i < pData->m_List.size(); i++)
  765. {
  766. pItem = pData->m_List.at(i);
  767. if (pItem->m_dwHandleType == HandleType)
  768. {
  769. if (bChildLock && !pItem->m_bLockOnChild)
  770. continue;
  771. delete pItem;
  772. pData->m_List.erase(&pData->m_List.at(i));
  773. pData->m_dwNumLocks--;
  774. bFound = TRUE;
  775. break;
  776. }
  777. }
  778. }
  779. if (bDelChildren)
  780. {
  781. // Remove this lock from all the
  782. // owner objects (namespaces, classes)
  783. // ===================================
  784. SQL_IDMap::iterator walk = pData->m_OwnerIds.begin();
  785. while (walk != pData->m_OwnerIds.end())
  786. {
  787. SQL_ID dId = (*walk).first;
  788. hr = DeleteLock(dId, true, (HandleType &~WMIDB_HANDLE_TYPE_SUBSCOPED), false, pObj);
  789. if (FAILED(hr))
  790. break;
  791. walk++;
  792. }
  793. // Remove this lock from the child
  794. // objects that we previously
  795. // locked out.
  796. // ===============================
  797. if (HandleType & WMIDB_HANDLE_TYPE_SUBSCOPED)
  798. {
  799. for (int i = 0; i < pData->m_List.size(); i++)
  800. {
  801. LockItem *pTemp = pData->m_List.at(i);
  802. if (pTemp && pTemp->m_dSourceId != 0)
  803. DeleteLock(pTemp->m_dSourceId, true, (HandleType &~WMIDB_HANDLE_TYPE_SUBSCOPED), false, pObj);
  804. }
  805. }
  806. }
  807. // If that worked, we can
  808. // remove this entry from the
  809. // the lock cache.
  810. // ===========================
  811. if (SUCCEEDED(hr))
  812. {
  813. pData->m_dwStatus = pData->GetMaxLock(true);
  814. pData->m_dwCompositeStatus = pData->GetMaxLock(false);
  815. // Delete if this is the last lock...
  816. if (!pData->m_dwNumLocks)
  817. hr = m_Cache.Delete(ObjId);
  818. }
  819. }
  820. else
  821. {
  822. // This object was deleted. We have to
  823. // invalidate all the handles for this object.
  824. // ==========================================
  825. LockItem *pItem = NULL;
  826. for (int i = 0; i < pData->m_List.size(); i++)
  827. {
  828. pItem = pData->m_List.at(i);
  829. if (pItem && pItem->m_pObj)
  830. ((CWmiDbHandle *)pItem->m_pObj)->m_dwHandleType = WMIDB_HANDLE_TYPE_INVALID;
  831. }
  832. hr = m_Cache.Delete(ObjId);
  833. }
  834. }
  835. else if (hr == WBEM_E_NOT_FOUND)
  836. hr = WBEM_S_NO_ERROR;
  837. return hr;
  838. }
  839. //***************************************************************************
  840. //
  841. // CLockCache::GetCurrentLock
  842. //
  843. //***************************************************************************
  844. HRESULT CLockCache::GetCurrentLock(SQL_ID ObjId, bool bImmediate, DWORD &HandleType, DWORD *Version)
  845. {
  846. HRESULT hr = WBEM_S_NO_ERROR;
  847. _WMILockit lkt(&m_cs);
  848. LockData *pData = NULL;
  849. LockData *temp;
  850. hr = m_Cache.Get(ObjId, &temp);
  851. if (SUCCEEDED(hr))
  852. {
  853. pData = (LockData *)temp;
  854. if (bImmediate)
  855. HandleType = pData->m_dwStatus;
  856. else
  857. HandleType = pData->m_dwCompositeStatus;
  858. if (Version)
  859. {
  860. if (bImmediate)
  861. *Version = pData->m_dwVersion;
  862. else
  863. *Version = pData->m_dwCompositeVersion;
  864. }
  865. }
  866. return hr;
  867. }
  868. //***************************************************************************
  869. //
  870. // CLockCache::GetAllLocks
  871. //
  872. //***************************************************************************
  873. HRESULT CLockCache::GetAllLocks(SQL_ID ObjId, SQL_ID ClassId, SQL_ID NsId, CSchemaCache *pSchema,
  874. bool bImmediate, DWORD &HandleType, DWORD *Version)
  875. {
  876. HRESULT hr = WBEM_S_NO_ERROR;
  877. DWORD dwCurrType = 0, dwTemp = 0;
  878. SQL_ID dParentId = 0;
  879. hr = GetCurrentLock(ObjId, bImmediate, dwCurrType, Version);
  880. if (SUCCEEDED(GetCurrentLock(ClassId, bImmediate, dwTemp)))
  881. {
  882. if (dwTemp & WMIDB_HANDLE_TYPE_SUBSCOPED)
  883. dwCurrType = GetMaxBytes(dwCurrType, dwTemp);
  884. }
  885. if (SUCCEEDED(GetCurrentLock(NsId, bImmediate, dwTemp)))
  886. {
  887. if (dwTemp & WMIDB_HANDLE_TYPE_SUBSCOPED)
  888. dwCurrType = GetMaxBytes(dwCurrType, dwTemp);
  889. }
  890. if (ClassId)
  891. {
  892. while (SUCCEEDED(pSchema->GetParentId(ClassId, dParentId)))
  893. {
  894. if (SUCCEEDED(GetCurrentLock(dParentId, bImmediate, dwTemp)))
  895. {
  896. if (dwTemp & WMIDB_HANDLE_TYPE_SUBSCOPED)
  897. dwCurrType = GetMaxBytes(dwCurrType, dwTemp);
  898. }
  899. ClassId = dParentId;
  900. }
  901. }
  902. HandleType = dwCurrType;
  903. return hr;
  904. }
  905. //***************************************************************************
  906. //
  907. // CLockCache::CanLockHandle
  908. //
  909. //***************************************************************************
  910. bool CLockCache::CanLockHandle (SQL_ID ObjId, DWORD RequestedHandleType, bool bImmediate, bool bSubscopedOnly)
  911. {
  912. bool bRet = true; // If not found, they can definitely lock it...
  913. DWORD dwCurrType = 0;
  914. _WMILockit lkt(&m_cs);
  915. LockData *pData = NULL;
  916. LockData *temp;
  917. HRESULT hr = m_Cache.Get(ObjId, &temp);
  918. if (SUCCEEDED(hr))
  919. {
  920. pData = (LockData *)temp;
  921. dwCurrType = pData->GetMaxLock(bImmediate, bSubscopedOnly);
  922. if (bRet)
  923. {
  924. switch (dwCurrType & 0xF)
  925. {
  926. case WMIDB_HANDLE_TYPE_COOKIE:
  927. case WMIDB_HANDLE_TYPE_VERSIONED: // Weak handles always succeed.
  928. bRet = true;
  929. break;
  930. case WMIDB_HANDLE_TYPE_EXCLUSIVE: // Exclusive access.
  931. if ((RequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_COOKIE &&
  932. (RequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_VERSIONED)
  933. bRet = false;
  934. break;
  935. case WMIDB_HANDLE_TYPE_PROTECTED: // Read only
  936. if ((RequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_EXCLUSIVE)
  937. bRet = true;
  938. else
  939. bRet = false;
  940. break;
  941. default:
  942. bRet = true;
  943. break;
  944. }
  945. }
  946. }
  947. return bRet;
  948. }
  949. //***************************************************************************
  950. //
  951. // CLockCache::CanRenderObject
  952. //
  953. //***************************************************************************
  954. bool CLockCache::CanRenderObject (SQL_ID ObjId, SQL_ID ClassId, SQL_ID NsId, CSchemaCache *pSchema, DWORD RequestedHandleType, bool bImmediate)
  955. {
  956. bool bRet = true; // If not found, they can definitely lock it...
  957. DWORD dwCurrType;
  958. SQL_ID dParentId = 0;
  959. // Get the lock for this
  960. // object and all its ancestors.
  961. // =============================
  962. HRESULT hr = GetAllLocks(ObjId, ClassId, NsId, pSchema, bImmediate, RequestedHandleType);
  963. if (SUCCEEDED(hr))
  964. {
  965. dwCurrType = RequestedHandleType & 0xF;
  966. switch (dwCurrType)
  967. {
  968. case WMIDB_HANDLE_TYPE_COOKIE:
  969. case WMIDB_HANDLE_TYPE_VERSIONED: // Weak handles always succeed.
  970. bRet = true;
  971. break;
  972. case WMIDB_HANDLE_TYPE_EXCLUSIVE: // Exclusive access.
  973. bRet = false;
  974. break;
  975. case WMIDB_HANDLE_TYPE_PROTECTED: // Read only
  976. if ((RequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_EXCLUSIVE)
  977. bRet = true;
  978. else
  979. bRet = false;
  980. break;
  981. default:
  982. bRet = true;
  983. break;
  984. }
  985. }
  986. return bRet;
  987. }
  988. //***************************************************************************
  989. //
  990. // CLockCache::IncrementVersion
  991. //
  992. //***************************************************************************
  993. HRESULT CLockCache::IncrementVersion(SQL_ID ObjId)
  994. {
  995. HRESULT hr = WBEM_S_NO_ERROR;
  996. _WMILockit lkt(&m_cs);
  997. LockData *pData = NULL;
  998. LockData *temp;
  999. hr = m_Cache.Get(ObjId, &temp);
  1000. if (SUCCEEDED(hr))
  1001. {
  1002. pData = (LockData *)temp;
  1003. pData->m_dwVersion++;
  1004. pData->m_dwCompositeVersion++;
  1005. }
  1006. return hr;
  1007. }
  1008. //***************************************************************************
  1009. //
  1010. // PropertyData::PropertyData
  1011. //
  1012. //***************************************************************************
  1013. PropertyData::PropertyData()
  1014. {
  1015. m_dwClassID = 0;
  1016. m_dwStorageType = 0;
  1017. m_dwCIMType = 0;
  1018. m_dwFlags = 0;
  1019. m_dwRefClassID = 0;
  1020. m_dwQPropID = 0;
  1021. m_dwFlavor = 0;
  1022. m_sPropertyName = NULL;
  1023. m_sDefaultValue = NULL;
  1024. }
  1025. //***************************************************************************
  1026. //
  1027. // PropertyData::GetSize
  1028. //
  1029. //***************************************************************************
  1030. DWORD PropertyData::GetSize()
  1031. {
  1032. DWORD dwSize = 0;
  1033. if (m_sPropertyName)
  1034. dwSize += wcslen(m_sPropertyName)*2;
  1035. else
  1036. dwSize += sizeof(LPWSTR);
  1037. if (m_sDefaultValue)
  1038. dwSize += wcslen(m_sDefaultValue)*2;
  1039. else
  1040. dwSize += sizeof(LPWSTR);
  1041. dwSize += sizeof(m_dwClassID) +
  1042. sizeof(m_dwStorageType) +
  1043. sizeof(m_dwCIMType) +
  1044. sizeof(m_dwFlags) +
  1045. sizeof(m_dwRefClassID) +
  1046. sizeof(m_dwQPropID) +
  1047. sizeof(m_dwFlavor);
  1048. return dwSize;
  1049. }
  1050. //***************************************************************************
  1051. //
  1052. // ClassData::ClassData
  1053. //
  1054. //***************************************************************************
  1055. ClassData::ClassData()
  1056. {
  1057. m_dwClassID = 0;
  1058. m_dwSuperClassID = 0;
  1059. m_dwDynastyID = 0;
  1060. m_dwScopeID = 0;
  1061. m_dwFlags = 0;
  1062. m_Properties = new PropertyList[10];
  1063. m_dwNumProps = 0;
  1064. m_dwArraySize = 10;
  1065. m_sName = NULL;
  1066. m_sObjectPath = NULL;
  1067. }
  1068. //***************************************************************************
  1069. //
  1070. // ClassData::GetSize
  1071. //
  1072. //***************************************************************************
  1073. DWORD ClassData::GetSize()
  1074. {
  1075. DWORD dwSize = 0;
  1076. if (m_sName)
  1077. dwSize += wcslen(m_sName)*2;
  1078. else
  1079. dwSize += sizeof(LPWSTR);
  1080. if (m_sObjectPath)
  1081. dwSize += wcslen(m_sObjectPath)*2;
  1082. else
  1083. dwSize += dwSize += sizeof(LPWSTR);
  1084. dwSize += sizeof(m_dwClassID) +
  1085. sizeof(m_dwSuperClassID) +
  1086. sizeof(m_dwDynastyID) +
  1087. sizeof(m_dwScopeID) +
  1088. sizeof(m_dwNumProps) +
  1089. sizeof(m_dwArraySize) +
  1090. sizeof(m_dwFlags);
  1091. for (int i=0; i < m_dwNumProps; i++)
  1092. {
  1093. dwSize += sizeof(PropertyList);
  1094. }
  1095. return dwSize;
  1096. }
  1097. //***************************************************************************
  1098. //
  1099. // ClassData::InsertProperty
  1100. //
  1101. //***************************************************************************
  1102. void ClassData::InsertProperty (DWORD PropId, BOOL bIsKey)
  1103. {
  1104. BOOL bFound = FALSE;
  1105. if (m_Properties)
  1106. {
  1107. for (int i = 0; i < m_dwNumProps; i++)
  1108. {
  1109. if (m_Properties[i].m_dwPropertyId == PropId)
  1110. {
  1111. bFound = TRUE;
  1112. m_Properties[i].m_bIsKey = bIsKey;
  1113. break;
  1114. }
  1115. }
  1116. if (!bFound)
  1117. {
  1118. if (m_dwNumProps == m_dwArraySize)
  1119. {
  1120. PropertyList *pList = new PropertyList[m_dwArraySize + 10];
  1121. if (pList)
  1122. {
  1123. memcpy(pList, m_Properties, sizeof(PropertyList) * m_dwArraySize);
  1124. delete m_Properties;
  1125. m_Properties = pList;
  1126. m_dwArraySize += 10;
  1127. }
  1128. }
  1129. m_Properties[m_dwNumProps].m_dwPropertyId = PropId;
  1130. m_Properties[m_dwNumProps].m_bIsKey = bIsKey;
  1131. m_dwNumProps++;
  1132. }
  1133. }
  1134. }
  1135. void ClassData::DeleteProperty (DWORD PropId)
  1136. {
  1137. // Should we clean up the gaps here?
  1138. if (m_Properties)
  1139. {
  1140. for (int i = 0; i < m_dwNumProps; i++)
  1141. {
  1142. if (m_Properties[i].m_dwPropertyId == PropId)
  1143. {
  1144. m_Properties[i].m_dwPropertyId = 0;
  1145. m_Properties[i].m_bIsKey = 0;
  1146. break;
  1147. }
  1148. }
  1149. }
  1150. }
  1151. void ClassData::InsertDerivedClass (SQL_ID dID)
  1152. {
  1153. BOOL bFound = FALSE;
  1154. for (int i = 0; i < m_DerivedIDs.size(); i++)
  1155. {
  1156. if (m_DerivedIDs.at(i) == dID)
  1157. {
  1158. bFound = TRUE;
  1159. break;
  1160. }
  1161. }
  1162. if (!bFound)
  1163. m_DerivedIDs.push_back(dID);
  1164. }
  1165. void ClassData::DeleteDerivedClass (SQL_ID dID)
  1166. {
  1167. for (int i = 0; i < m_DerivedIDs.size(); i++)
  1168. {
  1169. if (m_DerivedIDs.at(i) == dID)
  1170. {
  1171. m_DerivedIDs.erase(&m_DerivedIDs.at(i));
  1172. break;
  1173. }
  1174. }
  1175. }
  1176. //***************************************************************************
  1177. //
  1178. // NamespaceData::GetSize
  1179. //
  1180. //***************************************************************************
  1181. DWORD NamespaceData::GetSize()
  1182. {
  1183. DWORD dwSize = 0;
  1184. if (m_sNamespaceName)
  1185. dwSize += wcslen(m_sNamespaceName)*2;
  1186. else
  1187. dwSize += sizeof(LPWSTR);
  1188. if (m_sNamespaceKey)
  1189. dwSize += wcslen(m_sNamespaceKey)*2;
  1190. else
  1191. dwSize += sizeof(LPWSTR);
  1192. dwSize += sizeof(m_dNamespaceId) +
  1193. sizeof(m_dParentId) +
  1194. sizeof(m_dClassId);
  1195. return dwSize;
  1196. }
  1197. //***************************************************************************
  1198. //
  1199. // CSchemaCache::CSchemaCache
  1200. //
  1201. //***************************************************************************
  1202. CSchemaCache::CSchemaCache()
  1203. {
  1204. m_dwTotalSize = 0;
  1205. m_dwMaxSize = 204800;
  1206. InitializeCriticalSection(&m_cs);
  1207. }
  1208. //***************************************************************************
  1209. //
  1210. // CSchemaCache::~CSchemaCache
  1211. //
  1212. //***************************************************************************
  1213. CSchemaCache::~CSchemaCache()
  1214. {
  1215. EmptyCache();
  1216. DeleteCriticalSection(&m_cs);
  1217. }
  1218. //***************************************************************************
  1219. //
  1220. // CSchemaCache::EmptyCache
  1221. //
  1222. //***************************************************************************
  1223. void CSchemaCache::EmptyCache()
  1224. {
  1225. _WMILockit lkt(&m_cs);
  1226. m_Cache.Empty();
  1227. m_CCache.Empty();
  1228. m_CIndex.clear();
  1229. m_dwTotalSize = 0;
  1230. }
  1231. //***************************************************************************
  1232. //
  1233. // CSchemaCache::GetPropertyInfo
  1234. //
  1235. //***************************************************************************
  1236. HRESULT CSchemaCache::GetPropertyInfo (DWORD dwPropertyID, _bstr_t *sName, SQL_ID *dwClassID, DWORD *dwStorageType,
  1237. DWORD *dwCIMType, DWORD *dwFlags, SQL_ID *dwRefClassID, _bstr_t *sDefaultValue, DWORD *pdwRefId, DWORD *pdwFlavor)
  1238. {
  1239. _WMILockit lkt(&m_cs);
  1240. HRESULT hr = WBEM_S_NO_ERROR;
  1241. PropertyData *pData = NULL;
  1242. SQL_ID dTemp = dwPropertyID;
  1243. m_Cache.Get(dTemp, &pData);
  1244. if (pData != NULL)
  1245. {
  1246. if (sName) *sName = pData->m_sPropertyName;
  1247. if (dwClassID) *dwClassID = pData->m_dwClassID;
  1248. if (dwStorageType) *dwStorageType = pData->m_dwStorageType;
  1249. if (dwCIMType) *dwCIMType = pData->m_dwCIMType;
  1250. if (dwFlags) *dwFlags = pData->m_dwFlags;
  1251. if (dwRefClassID) *dwRefClassID = pData->m_dwRefClassID;
  1252. if (sDefaultValue) *sDefaultValue = pData->m_sDefaultValue;
  1253. if (pdwRefId) *pdwRefId = pData->m_dwQPropID;
  1254. if (pdwFlavor) *pdwFlavor = pData->m_dwFlavor;
  1255. }
  1256. else
  1257. hr = WBEM_E_NOT_FOUND;
  1258. return hr;
  1259. }
  1260. //***************************************************************************
  1261. //
  1262. // CSchemaCache::GetPropertyID
  1263. //
  1264. //***************************************************************************
  1265. HRESULT CSchemaCache::GetPropertyID (LPCWSTR lpName, SQL_ID dClassID, DWORD dwFlags, CIMTYPE ct,
  1266. DWORD &PropertyID, SQL_ID *ActualClass, DWORD *Flags, DWORD *Type, BOOL bSys)
  1267. {
  1268. HRESULT hr = WBEM_S_NO_ERROR;
  1269. _WMILockit lkt(&m_cs);
  1270. _bstr_t sIndexKey;
  1271. SQL_ID dCurrClass = dClassID;
  1272. PropertyID = 0;
  1273. if (lpName && wcslen(lpName) > 2 && lpName[0] == L'_' && lpName[1] == L'_')
  1274. bSys = TRUE;
  1275. // Try to find this property in this class,
  1276. // or its parent classes.
  1277. if (dClassID)
  1278. {
  1279. ClassData *pClass = NULL;
  1280. m_CCache.Get(dClassID, &pClass);
  1281. while (pClass)
  1282. {
  1283. for (int i = 0; i < pClass->m_dwNumProps; i++)
  1284. {
  1285. DWORD dwPropertyID = pClass->m_Properties[i].m_dwPropertyId;
  1286. PropertyData *pPData = NULL;
  1287. SQL_ID dTemp = dwPropertyID;
  1288. m_Cache.Get(dTemp, &pPData);
  1289. if (!pPData)
  1290. continue;
  1291. if (!_wcsnicmp(pPData->m_sPropertyName, lpName, MAX_WIDTH_SCHEMANAME))
  1292. {
  1293. BOOL bMatch = TRUE;
  1294. if ((dwFlags & REPDRVR_FLAG_NONPROP) ==
  1295. (pPData->m_dwFlags & REPDRVR_FLAG_NONPROP))
  1296. {
  1297. if (dwFlags & REPDRVR_FLAG_NONPROP)
  1298. {
  1299. if (ct != REPDRVR_IGNORE_CIMTYPE)
  1300. {
  1301. if (ct != pPData->m_dwCIMType)
  1302. bMatch = FALSE;
  1303. }
  1304. }
  1305. if (bMatch)
  1306. {
  1307. if (ActualClass)
  1308. *ActualClass = dCurrClass;
  1309. if (Flags)
  1310. *Flags = pPData->m_dwFlags;
  1311. if (Type)
  1312. *Type = pPData->m_dwStorageType;
  1313. PropertyID = dwPropertyID;
  1314. }
  1315. break;
  1316. }
  1317. }
  1318. }
  1319. dCurrClass = pClass->m_dwSuperClassID;
  1320. if (PropertyID || !dCurrClass)
  1321. break;
  1322. pClass = NULL;
  1323. m_CCache.Get(dCurrClass, &pClass);
  1324. }
  1325. }
  1326. else
  1327. {
  1328. CListElement *pNext = m_Cache.FindFirst();
  1329. while (pNext)
  1330. {
  1331. SQL_ID dLast = pNext->m_dId;
  1332. PropertyData *pTemp = (PropertyData *)pNext->m_pObj;
  1333. if (pTemp)
  1334. {
  1335. if (!_wcsnicmp(pTemp->m_sPropertyName,lpName, MAX_WIDTH_SCHEMANAME))
  1336. {
  1337. PropertyID = pNext->m_dId;
  1338. if (ActualClass)
  1339. *ActualClass = pTemp->m_dwClassID;
  1340. if (Flags)
  1341. *Flags = pTemp->m_dwFlags;
  1342. if (Type)
  1343. *Type = pTemp->m_dwStorageType;
  1344. break;
  1345. }
  1346. }
  1347. delete pNext;
  1348. pNext = m_Cache.FindNext(dLast);
  1349. }
  1350. }
  1351. if (PropertyID == 0)
  1352. {
  1353. if (!bSys)
  1354. hr = WBEM_E_NOT_FOUND;
  1355. else if (dClassID!= 1)
  1356. hr = GetPropertyID(lpName, 1, dwFlags, ct, PropertyID, ActualClass, Flags, Type, FALSE);
  1357. }
  1358. return hr;
  1359. }
  1360. //***************************************************************************
  1361. //
  1362. // CSchemaCache::AddPropertyInfo
  1363. //
  1364. //***************************************************************************
  1365. HRESULT CSchemaCache::AddPropertyInfo (DWORD dwPropertyID, LPCWSTR lpName, SQL_ID dwClassID, DWORD dwStorageType,
  1366. DWORD dwCIMType, DWORD dwFlags, SQL_ID dwRefClassID, LPCWSTR lpDefault, DWORD dwRefPropID, DWORD dwFlavor)
  1367. {
  1368. _WMILockit lkt(&m_cs);
  1369. HRESULT hr = WBEM_S_NO_ERROR;
  1370. PropertyData *pData = NULL;
  1371. SQL_ID dTemp = dwPropertyID;
  1372. m_Cache.Get(dTemp, &pData);
  1373. if (pData == NULL)
  1374. {
  1375. pData = new PropertyData;
  1376. if (!pData)
  1377. hr = WBEM_E_OUT_OF_MEMORY;
  1378. else
  1379. m_Cache.Insert(dTemp, pData);
  1380. }
  1381. else
  1382. m_dwTotalSize -= pData->GetSize();
  1383. if (pData)
  1384. {
  1385. bool bTruncated = FALSE;
  1386. delete pData->m_sPropertyName;
  1387. pData->m_sPropertyName = TruncateLongText(lpName, MAX_WIDTH_SCHEMANAME,
  1388. bTruncated, MAX_WIDTH_SCHEMANAME, FALSE);
  1389. if (!pData->m_dwClassID)
  1390. pData->m_dwClassID = dwClassID;
  1391. pData->m_dwStorageType = dwStorageType;
  1392. pData->m_dwCIMType = dwCIMType;
  1393. pData->m_dwFlags = dwFlags;
  1394. pData->m_dwRefClassID = dwRefClassID;
  1395. pData->m_dwQPropID = dwRefPropID;
  1396. pData->m_dwFlavor = dwFlavor;
  1397. ClassData *pCData = NULL;
  1398. m_CCache.Get(dwClassID, &pCData);
  1399. if (pCData)
  1400. {
  1401. pCData->InsertProperty(dwPropertyID, FALSE);
  1402. if (dwFlags & REPDRVR_FLAG_KEYHOLE)
  1403. pCData->m_dwFlags |= REPDRVR_FLAG_KEYHOLE;
  1404. if (dwStorageType == WMIDB_STORAGE_IMAGE)
  1405. pCData->m_dwFlags |= REPDRVR_FLAG_IMAGE;
  1406. if (dwCIMType == CIM_OBJECT)
  1407. pCData->m_dwFlags |= REPDRVR_FLAG_IMAGE;
  1408. m_dwTotalSize += pCData->GetSize();
  1409. }
  1410. m_dwTotalSize += pData->GetSize();
  1411. }
  1412. return hr;
  1413. }
  1414. //***************************************************************************
  1415. //
  1416. // CSchemaCache::PropertyChanged
  1417. //
  1418. //***************************************************************************
  1419. bool CSchemaCache::PropertyChanged (LPCWSTR lpName, SQL_ID dwClassID, DWORD dwCIMType, LPCWSTR lpDefault,
  1420. DWORD dwFlags, SQL_ID dwRefClassID, DWORD dwRefPropID, DWORD dwFlavor)
  1421. {
  1422. _WMILockit lkt(&m_cs);
  1423. bool bChg = true;
  1424. HRESULT hr = WBEM_S_NO_ERROR;
  1425. DWORD dwPropertyID = 0;
  1426. PropertyData *pData = NULL;
  1427. hr = GetPropertyID(lpName, dwClassID, dwFlags, dwCIMType, dwPropertyID);
  1428. if (SUCCEEDED(hr))
  1429. {
  1430. SQL_ID dTemp = dwPropertyID;
  1431. m_Cache.Get(dTemp, &pData);
  1432. if (pData != NULL)
  1433. {
  1434. bChg = false;
  1435. if (pData->m_dwFlags != dwFlags ||
  1436. pData->m_dwCIMType != dwCIMType ||
  1437. pData->m_dwRefClassID != dwRefClassID ||
  1438. pData->m_dwQPropID != dwRefPropID ||
  1439. _wcsicmp(pData->m_sDefaultValue,lpDefault) ||
  1440. pData->m_dwFlavor != dwFlavor)
  1441. bChg = true;
  1442. }
  1443. }
  1444. return bChg;
  1445. }
  1446. //***************************************************************************
  1447. //
  1448. // CSchemaCache::IsQualifier
  1449. //
  1450. //***************************************************************************
  1451. bool CSchemaCache::IsQualifier(DWORD dwPropertyId)
  1452. {
  1453. bool bRet = false;
  1454. _WMILockit lkt(&m_cs);
  1455. PropertyData *pData = NULL;
  1456. SQL_ID dTemp = dwPropertyId;
  1457. m_Cache.Get(dTemp, &pData);
  1458. if (pData)
  1459. {
  1460. if (pData->m_dwFlags & REPDRVR_FLAG_QUALIFIER)
  1461. bRet = true;
  1462. }
  1463. return bRet;
  1464. }
  1465. //***************************************************************************
  1466. //
  1467. // CSchemaCache::SetAuxiliaryPropertyInfo
  1468. //
  1469. //***************************************************************************
  1470. HRESULT CSchemaCache::SetAuxiliaryPropertyInfo (DWORD dwPropertyID, LPWSTR lpDefault, DWORD dwRefID)
  1471. {
  1472. HRESULT hr = WBEM_S_NO_ERROR;
  1473. PropertyData *pData = NULL;
  1474. SQL_ID dTemp = dwPropertyID;
  1475. m_Cache.Get(dTemp, &pData);
  1476. if (pData)
  1477. {
  1478. delete pData->m_sDefaultValue;
  1479. pData->m_sDefaultValue = Macro_CloneLPWSTR(lpDefault);
  1480. pData->m_dwQPropID = dwRefID;
  1481. }
  1482. else
  1483. hr = WBEM_E_NOT_FOUND;
  1484. return hr;
  1485. }
  1486. //***************************************************************************
  1487. //
  1488. // CSchemaCache::DeleteProperty
  1489. //
  1490. //***************************************************************************
  1491. HRESULT CSchemaCache::DeleteProperty (DWORD dwPropertyID, SQL_ID dClassId)
  1492. {
  1493. _WMILockit lkt(&m_cs);
  1494. HRESULT hr = WBEM_S_NO_ERROR;
  1495. PropertyData *pData = NULL;
  1496. SQL_ID dTemp = dwPropertyID;
  1497. m_Cache.Get(dTemp, &pData);
  1498. if (pData)
  1499. {
  1500. SQL_ID dwClassID = pData->m_dwClassID;
  1501. if (dwClassID == dClassId)
  1502. {
  1503. m_dwTotalSize -= pData->GetSize();
  1504. // delete pData;
  1505. m_Cache.Delete(dwPropertyID);
  1506. ClassData *pCData = NULL;
  1507. m_CCache.Get(dwClassID, &pCData);
  1508. if (pCData)
  1509. {
  1510. m_dwTotalSize -= pCData->GetSize();
  1511. pCData->DeleteProperty(dwPropertyID);
  1512. }
  1513. }
  1514. }
  1515. return hr;
  1516. }
  1517. //***************************************************************************
  1518. //
  1519. // CSchemaCache::GetClassInfo
  1520. //
  1521. //***************************************************************************
  1522. HRESULT CSchemaCache::GetClassInfo (SQL_ID dwClassID, _bstr_t &sPath, SQL_ID &dwSuperClassID, SQL_ID &dwScopeID,
  1523. DWORD &dwTemp, _bstr_t *pName)
  1524. {
  1525. _WMILockit lkt(&m_cs);
  1526. HRESULT hr = WBEM_S_NO_ERROR;
  1527. ClassData *pClass = NULL;
  1528. m_CCache.Get(dwClassID, &pClass);
  1529. if (pClass)
  1530. {
  1531. sPath = pClass->m_sObjectPath;
  1532. if (pName)
  1533. *pName = pClass->m_sName;
  1534. dwSuperClassID = pClass->m_dwSuperClassID;
  1535. dwScopeID = pClass->m_dwScopeID;
  1536. dwTemp = pClass->m_dwFlags;
  1537. }
  1538. else
  1539. hr = WBEM_E_NOT_FOUND;
  1540. return hr;
  1541. }
  1542. //***************************************************************************
  1543. //
  1544. // CSchemaCache::AddClassInfo
  1545. //
  1546. //***************************************************************************
  1547. HRESULT CSchemaCache::AddClassInfo (SQL_ID dwClassID, LPCWSTR lpName, SQL_ID dwSuperClassID, SQL_ID dDynastyId, SQL_ID dwScopeID,
  1548. LPCWSTR lpPath, DWORD dwFlags)
  1549. {
  1550. _WMILockit lkt(&m_cs);
  1551. HRESULT hr = WBEM_S_NO_ERROR;
  1552. ClassData *pClass = NULL;
  1553. m_CCache.Get(dwClassID, &pClass);
  1554. if (!pClass)
  1555. {
  1556. pClass = new ClassData;
  1557. if (!pClass)
  1558. hr = WBEM_E_OUT_OF_MEMORY;
  1559. }
  1560. else
  1561. m_dwTotalSize -= pClass->GetSize();
  1562. if (pClass)
  1563. {
  1564. m_CCache.Insert(dwClassID, pClass);
  1565. wchar_t *wTemp = new wchar_t [MAX_WIDTH_SCHEMANAME+30];
  1566. CDeleteMe <wchar_t> r (wTemp);
  1567. if (wTemp)
  1568. {
  1569. bool bTruncated = FALSE;
  1570. delete pClass->m_sName;
  1571. pClass->m_sName = TruncateLongText(lpName, MAX_WIDTH_SCHEMANAME,
  1572. bTruncated, MAX_WIDTH_SCHEMANAME, FALSE);
  1573. if (wcslen(pClass->m_sName))
  1574. {
  1575. swprintf(wTemp , L"%s_%I64d", pClass->m_sName, dwScopeID);
  1576. m_CIndex[_bstr_t(wTemp)] = dwClassID;
  1577. }
  1578. pClass->m_dwClassID = dwClassID;
  1579. pClass->m_dwSuperClassID = dwSuperClassID;
  1580. pClass->m_dwDynastyID = dDynastyId;
  1581. pClass->m_dwScopeID = dwScopeID;
  1582. delete pClass->m_sObjectPath;
  1583. pClass->m_sObjectPath = Macro_CloneLPWSTR(lpPath);
  1584. pClass->m_dwFlags = dwFlags;
  1585. m_dwTotalSize += pClass->GetSize();
  1586. }
  1587. else
  1588. hr = WBEM_E_OUT_OF_MEMORY;
  1589. }
  1590. if (dwSuperClassID)
  1591. {
  1592. hr = m_CCache.Get(dwSuperClassID, &pClass);
  1593. if (FAILED(hr))
  1594. {
  1595. hr = AddClassInfo(dwSuperClassID, L"", 0, 0, 0, L"", 0);
  1596. if (SUCCEEDED(hr))
  1597. {
  1598. hr = m_CCache.Get(dwSuperClassID, &pClass);
  1599. }
  1600. }
  1601. if (SUCCEEDED(hr))
  1602. {
  1603. pClass->InsertDerivedClass(dwClassID);
  1604. }
  1605. }
  1606. return hr;
  1607. }
  1608. //***************************************************************************
  1609. //
  1610. // CSchemaCache::DeleteClass
  1611. //
  1612. //***************************************************************************
  1613. HRESULT CSchemaCache::DeleteClass (SQL_ID dwClassID)
  1614. {
  1615. _WMILockit lkt(&m_cs);
  1616. HRESULT hr = WBEM_S_NO_ERROR;
  1617. SQL_ID dParent = 0;
  1618. // Ignore requests to delete meta_class.
  1619. if (dwClassID == 1)
  1620. return WBEM_S_NO_ERROR;
  1621. ClassData *pClass = NULL;
  1622. m_CCache.Get(dwClassID, &pClass);
  1623. if (pClass)
  1624. {
  1625. dParent = pClass->m_dwSuperClassID;
  1626. wchar_t *wTemp = new wchar_t [wcslen(pClass->m_sName)+25];
  1627. CDeleteMe <wchar_t> r (wTemp);
  1628. if (wTemp)
  1629. {
  1630. swprintf(wTemp, L"%s_%I64d", pClass->m_sName, pClass->m_dwScopeID);
  1631. for (int i = 0; i < pClass->m_dwNumProps; i++)
  1632. DeleteProperty(pClass->m_Properties[i].m_dwPropertyId, dwClassID);
  1633. if (dParent != 0 && dParent != 1)
  1634. {
  1635. hr = m_CCache.Get(dParent, &pClass);
  1636. if (SUCCEEDED(hr))
  1637. {
  1638. m_dwTotalSize -= pClass->GetSize();
  1639. pClass->DeleteDerivedClass(dwClassID);
  1640. }
  1641. }
  1642. ClassNames::iterator it = m_CIndex.find(wTemp);
  1643. if (it != m_CIndex.end())
  1644. m_CIndex.erase(it);
  1645. m_CCache.Delete(dwClassID);
  1646. }
  1647. else
  1648. hr = WBEM_E_OUT_OF_MEMORY;
  1649. }
  1650. return hr;
  1651. }
  1652. //***************************************************************************
  1653. //
  1654. // CSchemaCache::GetClassID
  1655. //
  1656. //***************************************************************************
  1657. HRESULT CSchemaCache::GetClassID (LPCWSTR lpName, SQL_ID dwScopeID, SQL_ID &dClassID, SQL_ID *pDynasty)
  1658. {
  1659. _WMILockit lkt(&m_cs);
  1660. HRESULT hr = WBEM_S_NO_ERROR;
  1661. BOOL bInNamespace = FALSE;
  1662. SQL_ID dClass;
  1663. dClassID = 0;
  1664. if (!lpName)
  1665. return WBEM_E_NOT_FOUND;
  1666. GetNamespaceClass(dwScopeID, dClass);
  1667. if (dClass == NAMESPACECLASSID ||
  1668. IsDerivedClass(NAMESPACECLASSID, dClass))
  1669. bInNamespace = TRUE;
  1670. SQL_ID dParent = 0;
  1671. bool bTrunc = FALSE;
  1672. LPWSTR lpClassName = TruncateLongText(lpName, MAX_WIDTH_SCHEMANAME,
  1673. bTrunc, MAX_WIDTH_SCHEMANAME, FALSE);
  1674. CDeleteMe<wchar_t> c (lpClassName);
  1675. int iLen = wcslen(lpClassName);
  1676. wchar_t *pTmp = new wchar_t [iLen+25];
  1677. CDeleteMe <wchar_t> r (pTmp);
  1678. if (pTmp)
  1679. {
  1680. swprintf(pTmp, L"%s_%I64d", lpClassName, dwScopeID);
  1681. dClassID = m_CIndex[pTmp];
  1682. if (!dClassID)
  1683. {
  1684. if (dwScopeID != 0)
  1685. {
  1686. // Check the hierarchy. Maybe this is
  1687. // under a different scope.
  1688. dParent = dwScopeID;
  1689. while (TRUE)
  1690. {
  1691. GetParentNamespace(dParent, dParent);
  1692. GetNamespaceClass(dParent, dClass);
  1693. if (dClass == NAMESPACECLASSID ||
  1694. IsDerivedClass(NAMESPACECLASSID, dClass))
  1695. {
  1696. if (bInNamespace)
  1697. break;
  1698. else
  1699. bInNamespace = TRUE;
  1700. }
  1701. swprintf(pTmp, L"%s_%I64d", lpClassName, dParent);
  1702. dClassID = m_CIndex[pTmp];
  1703. if (!dParent || dClassID)
  1704. break;
  1705. }
  1706. }
  1707. if (!dClassID)
  1708. {
  1709. swprintf(pTmp, L"%s_0", lpClassName);
  1710. dClassID = m_CIndex[pTmp];
  1711. }
  1712. }
  1713. if (!dClassID)
  1714. hr = WBEM_E_NOT_FOUND;
  1715. else if (pDynasty)
  1716. {
  1717. ClassData *pClass = NULL;
  1718. hr = m_CCache.Get(dClassID, &pClass);
  1719. if (SUCCEEDED(hr))
  1720. *pDynasty = pClass->m_dwDynastyID;
  1721. }
  1722. }
  1723. else
  1724. hr = WBEM_E_OUT_OF_MEMORY;
  1725. return hr;
  1726. }
  1727. //***************************************************************************
  1728. //
  1729. // CSchemaCache::GetDynasty
  1730. //
  1731. //***************************************************************************
  1732. HRESULT CSchemaCache::GetDynasty (SQL_ID dClassId, SQL_ID &dDynasty, _bstr_t &sClassName)
  1733. {
  1734. HRESULT hr = 0;
  1735. _WMILockit lk(&m_cs);
  1736. ClassData *pClass = NULL;
  1737. dDynasty = 0;
  1738. hr = m_CCache.Get(dClassId, &pClass);
  1739. if (SUCCEEDED(hr))
  1740. {
  1741. if (pClass->m_dwSuperClassID == 1 || pClass->m_dwSuperClassID == 0)
  1742. {
  1743. dDynasty = dClassId;
  1744. sClassName = pClass->m_sName;
  1745. }
  1746. else
  1747. {
  1748. hr = GetDynasty(pClass->m_dwSuperClassID, dDynasty, sClassName);
  1749. }
  1750. }
  1751. return hr;
  1752. }
  1753. //***************************************************************************
  1754. //
  1755. // CSchemaCache::GetNamespaceID
  1756. //
  1757. //***************************************************************************
  1758. HRESULT CSchemaCache::GetNamespaceID(LPCWSTR lpKey, SQL_ID &dObjectId)
  1759. {
  1760. _WMILockit lkt(&m_cs);
  1761. HRESULT hr = WBEM_S_NO_ERROR;
  1762. _bstr_t sName = lpKey;
  1763. if (!sName.length())
  1764. sName = L"root";
  1765. dObjectId = CRC64::GenerateHashValue(sName);
  1766. if (!m_NamespaceIds.Exists(dObjectId))
  1767. hr = WBEM_E_NOT_FOUND;
  1768. return hr;
  1769. }
  1770. //***************************************************************************
  1771. //
  1772. // CSchemaCache::GetNamespaceClass
  1773. //
  1774. //***************************************************************************
  1775. HRESULT CSchemaCache::GetNamespaceClass(SQL_ID dScopeId, SQL_ID &dScopeClassId)
  1776. {
  1777. NamespaceData *pTemp = NULL;
  1778. HRESULT hr = m_NamespaceIds.Get(dScopeId, &pTemp);
  1779. if (SUCCEEDED(hr))
  1780. {
  1781. dScopeClassId=pTemp->m_dClassId;
  1782. }
  1783. return hr;
  1784. }
  1785. //***************************************************************************
  1786. //
  1787. // CSchemaCache::GetParentNamespace
  1788. //
  1789. //***************************************************************************
  1790. HRESULT CSchemaCache::GetParentNamespace(SQL_ID dObjectId, SQL_ID &dParentId, SQL_ID *dParentClassId)
  1791. {
  1792. HRESULT hr = WBEM_S_NO_ERROR;
  1793. _WMILockit lkt(&m_cs);
  1794. dParentId = 0;
  1795. if (dObjectId)
  1796. {
  1797. NamespaceData *pTemp = NULL;
  1798. hr = m_NamespaceIds.Get(dObjectId, &pTemp);
  1799. if (SUCCEEDED(hr))
  1800. {
  1801. dParentId = pTemp->m_dParentId;
  1802. if (dParentClassId && dParentId)
  1803. {
  1804. m_NamespaceIds.Get(dParentId, &pTemp);
  1805. *dParentClassId = pTemp->m_dClassId;
  1806. }
  1807. else if (dParentClassId)
  1808. *dParentClassId = 0;
  1809. }
  1810. }
  1811. else
  1812. hr = WBEM_E_INVALID_PARAMETER;
  1813. return hr;
  1814. }
  1815. //***************************************************************************
  1816. //
  1817. // CSchemaCache::GetNamespaceName
  1818. //
  1819. //***************************************************************************
  1820. HRESULT CSchemaCache::GetNamespaceName(SQL_ID dObjectId, _bstr_t *sName, _bstr_t *sKey)
  1821. {
  1822. HRESULT hr = WBEM_S_NO_ERROR;
  1823. _WMILockit lkt(&m_cs);
  1824. if (dObjectId)
  1825. {
  1826. NamespaceData *pTemp = NULL;
  1827. hr = m_NamespaceIds.Get(dObjectId, &pTemp);
  1828. if (SUCCEEDED(hr))
  1829. {
  1830. if (sName)
  1831. *sName = pTemp->m_sNamespaceName;
  1832. if (sKey)
  1833. *sKey = pTemp->m_sNamespaceName;
  1834. }
  1835. }
  1836. return hr;
  1837. }
  1838. //***************************************************************************
  1839. //
  1840. // CSchemaCache::AddNamespace
  1841. //
  1842. //***************************************************************************
  1843. HRESULT CSchemaCache::AddNamespace(LPCWSTR lpName, LPCWSTR lpKey, SQL_ID dObjectId, SQL_ID dParentId, SQL_ID dClassId)
  1844. {
  1845. _WMILockit lkt(&m_cs);
  1846. HRESULT hr = WBEM_S_NO_ERROR;
  1847. if (dParentId == dObjectId)
  1848. hr = WBEM_E_INVALID_PARAMETER;
  1849. else
  1850. {
  1851. // We need to generate an artificial key here,
  1852. // since our real key was generated from a compressed
  1853. // version of the key.
  1854. if (lpName && wcslen(lpName) && dObjectId != 0)
  1855. {
  1856. NamespaceData *pTemp = new NamespaceData;
  1857. if (pTemp)
  1858. {
  1859. pTemp->m_dNamespaceId = dObjectId;
  1860. delete pTemp->m_sNamespaceName;
  1861. pTemp->m_sNamespaceName = Macro_CloneLPWSTR(lpName);
  1862. pTemp->m_dParentId = dParentId;
  1863. pTemp->m_dClassId = dClassId;
  1864. m_NamespaceIds.Insert(dObjectId, pTemp);
  1865. m_dwTotalSize += pTemp->GetSize();
  1866. }
  1867. else
  1868. hr = WBEM_E_OUT_OF_MEMORY;
  1869. }
  1870. else
  1871. hr = WBEM_E_INVALID_PARAMETER;
  1872. }
  1873. return hr;
  1874. }
  1875. //***************************************************************************
  1876. //
  1877. // CSchemaCache::DeleteNamespace
  1878. //
  1879. //***************************************************************************
  1880. HRESULT CSchemaCache::DeleteNamespace(SQL_ID dId)
  1881. {
  1882. _WMILockit lkt(&m_cs);
  1883. HRESULT hr = 0;
  1884. if (dId)
  1885. {
  1886. NamespaceData *pTemp = NULL;
  1887. hr = m_NamespaceIds.Get(dId, &pTemp);
  1888. if (SUCCEEDED(hr))
  1889. {
  1890. pTemp -= pTemp->GetSize();
  1891. m_NamespaceIds.Delete(dId);
  1892. }
  1893. hr = WBEM_S_NO_ERROR;
  1894. }
  1895. else
  1896. hr = WBEM_E_INVALID_PARAMETER;
  1897. return hr;
  1898. }
  1899. //***************************************************************************
  1900. //
  1901. // CSchemaCache::IsSubScope
  1902. //
  1903. //***************************************************************************
  1904. bool CSchemaCache::IsSubScope(SQL_ID dParent, SQL_ID dPotentialSubScope)
  1905. {
  1906. bool bRet = false;
  1907. SQL_ID dParentID, dScopeClass = 0;
  1908. HRESULT hr = GetParentNamespace(dPotentialSubScope, dParentID, &dScopeClass);
  1909. while (SUCCEEDED(hr))
  1910. {
  1911. if (dParent == dParentID)
  1912. {
  1913. bRet = true;
  1914. break;
  1915. }
  1916. // Stop when we hit our own namespace
  1917. if (IsDerivedClass(NAMESPACECLASSID, dParent))
  1918. break;
  1919. hr = GetParentNamespace(dParentID, dParentID);
  1920. }
  1921. return bRet;
  1922. }
  1923. //***************************************************************************
  1924. //
  1925. // CSchemaCache::GetSubScopes
  1926. //
  1927. //***************************************************************************
  1928. HRESULT CSchemaCache::GetSubScopes(SQL_ID dId, SQL_ID **ppScopes, int &iNumScopes)
  1929. {
  1930. HRESULT hr = 0;
  1931. int iSize = 10;
  1932. iNumScopes = 0;
  1933. SQL_ID *pTemp = new SQL_ID [iSize];
  1934. if (!pTemp)
  1935. return WBEM_E_OUT_OF_MEMORY;
  1936. CListElement *pData = NULL;
  1937. SQL_ID dPrevious = 0;
  1938. pData = m_NamespaceIds.FindFirst();
  1939. while (pData != NULL && SUCCEEDED(hr))
  1940. {
  1941. dPrevious = pData->m_dId;
  1942. if (IsSubScope(dId, pData->m_dId))
  1943. {
  1944. if (iNumScopes >= iSize)
  1945. {
  1946. iSize += 10;
  1947. SQL_ID *ppNew = new SQL_ID [iSize];
  1948. if (ppNew)
  1949. {
  1950. memcpy(ppNew, pTemp, sizeof(SQL_ID) * iSize-10);
  1951. delete pTemp;
  1952. pTemp = ppNew;
  1953. }
  1954. else
  1955. {
  1956. hr = WBEM_E_OUT_OF_MEMORY;
  1957. break;
  1958. }
  1959. }
  1960. pTemp[iNumScopes] = pData->m_dId;
  1961. iNumScopes++;
  1962. }
  1963. delete pData;
  1964. pData = m_NamespaceIds.FindNext(dPrevious);
  1965. if (!pData)
  1966. break;
  1967. }
  1968. *ppScopes = pTemp;
  1969. return hr;
  1970. }
  1971. //***************************************************************************
  1972. //
  1973. // CSchemaCache::GetClassObject
  1974. //
  1975. //***************************************************************************
  1976. HRESULT CSchemaCache::GetClassObject (LPWSTR lpMachineName, LPWSTR lpNamespaceName, SQL_ID dScopeId,
  1977. SQL_ID dClassId, IWbemClassObject *pTemp)
  1978. {
  1979. _WMILockit lkt(&m_cs);
  1980. HRESULT hr = WBEM_S_NO_ERROR;
  1981. IWbemQualifierSet *pQS = NULL;
  1982. ClassData *pData = NULL;
  1983. m_CCache.Get(dClassId, &pData);
  1984. if (!pData)
  1985. hr = WBEM_E_NOT_FOUND;
  1986. else
  1987. {
  1988. if (SUCCEEDED(hr))
  1989. {
  1990. VARIANT var;
  1991. VariantInit(&var);
  1992. // __CLASS
  1993. V_BSTR(&var) = Macro_CloneLPWSTR(pData->m_sName);
  1994. var.vt = VT_BSTR;
  1995. hr = pTemp->Put(L"__Class", 0, &var, CIM_STRING);
  1996. VariantClear(&var);
  1997. hr = DecorateWbemObj(lpMachineName, lpNamespaceName, dScopeId, pTemp, dClassId);
  1998. // Set common qualifiers.
  1999. pTemp->GetQualifierSet(&pQS);
  2000. if (pData->m_dwFlags & REPDRVR_FLAG_ABSTRACT)
  2001. SetBoolQualifier(pQS, L"abstract", 0);
  2002. pQS->Release();
  2003. // Get every property and qualifier
  2004. // for this class and all its parents.
  2005. // =======================================
  2006. hr = WBEM_S_NO_ERROR;
  2007. while (TRUE)
  2008. {
  2009. for (int i = 0; i < pData->m_dwNumProps; i++)
  2010. {
  2011. DWORD dwPropertyID = pData->m_Properties[i].m_dwPropertyId;
  2012. PropertyData *pPData = NULL;
  2013. SQL_ID dTemp = dwPropertyID;
  2014. m_Cache.Get(dTemp, &pPData);
  2015. if (!pPData)
  2016. continue;
  2017. if (pPData->m_dwFlags & REPDRVR_FLAG_SYSTEM)
  2018. continue;
  2019. // If the property is an embedded object, we
  2020. // need to instantiate a new instance of this
  2021. // class and add it. Each property/qualifier
  2022. // will need to be added also.
  2023. // ===========================================
  2024. if (!(pPData->m_dwFlags & REPDRVR_FLAG_QUALIFIER) && !(pPData->m_dwFlags & REPDRVR_FLAG_METHOD)
  2025. && !(pPData->m_dwFlags & REPDRVR_FLAG_IN_PARAM) && !(pPData->m_dwFlags & REPDRVR_FLAG_OUT_PARAM))
  2026. {
  2027. IWbemQualifierSet *pQS = NULL;
  2028. CIMTYPE ct = pPData->m_dwCIMType;
  2029. if (pPData->m_dwFlags & REPDRVR_FLAG_ARRAY)
  2030. {
  2031. ct |= CIM_FLAG_ARRAY;
  2032. var.vt = VT_NULL;
  2033. }
  2034. else
  2035. {
  2036. if (wcslen(pPData->m_sDefaultValue) > 0)
  2037. {
  2038. V_BSTR(&var) = SysAllocString(pPData->m_sDefaultValue);
  2039. var.vt = VT_BSTR;
  2040. }
  2041. else
  2042. {
  2043. var.vt = VT_NULL;
  2044. }
  2045. }
  2046. hr = pTemp->Put(pPData->m_sPropertyName, 0, &var, ct);
  2047. VariantClear(&var);
  2048. }
  2049. }
  2050. if (FAILED(hr))
  2051. break;
  2052. for (i = 0; i < pData->m_dwNumProps; i++)
  2053. {
  2054. DWORD dwPropertyID = pData->m_Properties[i].m_dwPropertyId;
  2055. PropertyData *pPData = NULL;
  2056. SQL_ID dTemp = dwPropertyID;
  2057. m_Cache.Get(dTemp, &pPData);
  2058. if (!pPData)
  2059. continue;
  2060. if (pPData->m_dwFlags & REPDRVR_FLAG_SYSTEM)
  2061. continue;
  2062. if (pPData->m_dwFlags & REPDRVR_FLAG_QUALIFIER)
  2063. {
  2064. if (wcslen(pPData->m_sDefaultValue))
  2065. {
  2066. IWbemQualifierSet *pQS = NULL;
  2067. if (pPData->m_dwQPropID != 0)
  2068. {
  2069. // property or method qualifier
  2070. PropertyData *pData = NULL;
  2071. SQL_ID dTemp = pPData->m_dwQPropID;
  2072. m_Cache.Get(dTemp, &pData);
  2073. if (pData)
  2074. {
  2075. if (pData->m_dwFlags & REPDRVR_FLAG_METHOD)
  2076. hr = pTemp->GetMethodQualifierSet(pData->m_sPropertyName, &pQS);
  2077. else
  2078. hr = pTemp->GetPropertyQualifierSet(pData->m_sPropertyName, &pQS);
  2079. }
  2080. else
  2081. hr = WBEM_E_NOT_FOUND;
  2082. if (SUCCEEDED(hr))
  2083. {
  2084. V_BSTR(&var) = SysAllocString(pPData->m_sDefaultValue);
  2085. var.vt = VT_BSTR;
  2086. pQS->Put(pPData->m_sPropertyName, &var, pPData->m_dwFlavor);
  2087. pQS->Release();
  2088. }
  2089. }
  2090. else
  2091. {
  2092. // class qualifier
  2093. hr = pTemp->GetQualifierSet(&pQS);
  2094. if (SUCCEEDED(hr))
  2095. {
  2096. V_BSTR(&var) = SysAllocString(pPData->m_sDefaultValue);
  2097. var.vt = VT_BSTR;
  2098. pQS->Put(pPData->m_sPropertyName, &var, pPData->m_dwFlavor);
  2099. pQS->Release();
  2100. }
  2101. }
  2102. }
  2103. }
  2104. else
  2105. {
  2106. IWbemClassObject *pIn = NULL, *pOut = NULL;
  2107. // This is a method or one of its parameters.
  2108. if (pPData->m_dwFlags & REPDRVR_FLAG_METHOD)
  2109. {
  2110. hr = pTemp->PutMethod(pPData->m_sPropertyName, 0, NULL, NULL);
  2111. }
  2112. else if ((pPData->m_dwFlags & REPDRVR_FLAG_IN_PARAM) ||
  2113. (pPData->m_dwFlags & REPDRVR_FLAG_OUT_PARAM))
  2114. {
  2115. // This is handled in GetObjectData.
  2116. }
  2117. }
  2118. VariantClear(&var);
  2119. }
  2120. if (pData->m_dwSuperClassID <= 1)
  2121. break;
  2122. else
  2123. {
  2124. m_CCache.Get(pData->m_dwSuperClassID, &pData);
  2125. if (!pData)
  2126. break;
  2127. }
  2128. if (FAILED(hr))
  2129. break;
  2130. }
  2131. }
  2132. }
  2133. return hr;
  2134. }
  2135. //***************************************************************************
  2136. //
  2137. // CSchemaCache::GetParentId
  2138. //
  2139. //***************************************************************************
  2140. HRESULT CSchemaCache::GetParentId (SQL_ID dClassId, SQL_ID &dParentId)
  2141. {
  2142. HRESULT hr = WBEM_S_NO_ERROR;
  2143. _WMILockit lkt(&m_cs);
  2144. ClassData *pData = NULL;
  2145. m_CCache.Get(dClassId, &pData);
  2146. if (pData)
  2147. {
  2148. dParentId = pData->m_dwSuperClassID;
  2149. if (!dParentId || dParentId == 1) // Disregard __Class.
  2150. hr = WBEM_E_NOT_FOUND;
  2151. }
  2152. else
  2153. hr = WBEM_E_NOT_FOUND;
  2154. return hr;
  2155. }
  2156. //***************************************************************************
  2157. //
  2158. // CSchemaCache::GetKeyholeProperty
  2159. //
  2160. //***************************************************************************
  2161. HRESULT CSchemaCache::GetKeyholeProperty (SQL_ID dClassId, DWORD &dwPropID, _bstr_t &sPropName)
  2162. {
  2163. HRESULT hr = WBEM_E_NOT_FOUND;
  2164. _WMILockit lkt(&m_cs);
  2165. ClassData *pData = NULL;
  2166. m_CCache.Get(dClassId, &pData);
  2167. if (pData)
  2168. {
  2169. if (pData->m_dwFlags & REPDRVR_FLAG_KEYHOLE)
  2170. {
  2171. // We know we have one.
  2172. for (int i = 0; i < pData->m_dwNumProps; i++)
  2173. {
  2174. DWORD dwPropertyID = pData->m_Properties[i].m_dwPropertyId;
  2175. PropertyData *pPData = NULL;
  2176. SQL_ID dTemp = dwPropertyID;
  2177. m_Cache.Get(dTemp, &pPData);
  2178. if (pPData && pPData->m_dwFlags & REPDRVR_FLAG_KEYHOLE)
  2179. {
  2180. dwPropID = dwPropertyID;
  2181. sPropName = pPData->m_sPropertyName;
  2182. hr = WBEM_S_NO_ERROR;
  2183. break;
  2184. }
  2185. }
  2186. }
  2187. }
  2188. return hr;
  2189. }
  2190. //***************************************************************************
  2191. //
  2192. // CSchemaCache::IsInHierarchy
  2193. //
  2194. //***************************************************************************
  2195. bool CSchemaCache::IsInHierarchy(SQL_ID dParentId, SQL_ID dPotentialChild)
  2196. {
  2197. HRESULT hr = WBEM_S_NO_ERROR;
  2198. bool bRet = false;
  2199. _WMILockit lk(&m_cs);
  2200. if (dParentId == dPotentialChild)
  2201. bRet = true;
  2202. else
  2203. {
  2204. bRet = IsDerivedClass(dParentId, dPotentialChild);
  2205. if (!bRet)
  2206. {
  2207. bRet = IsDerivedClass(dPotentialChild, dParentId);
  2208. }
  2209. }
  2210. return bRet;
  2211. }
  2212. //***************************************************************************
  2213. //
  2214. // CSchemaCache::IsDerivedClass
  2215. //
  2216. //***************************************************************************
  2217. bool CSchemaCache::IsDerivedClass(SQL_ID dParentId, SQL_ID dPotentialChild)
  2218. {
  2219. HRESULT hr = WBEM_S_NO_ERROR;
  2220. bool bRet = false;
  2221. _WMILockit lk(&m_cs);
  2222. ClassData *pData = NULL;
  2223. hr = m_CCache.Get(dPotentialChild, &pData);
  2224. while (SUCCEEDED(hr))
  2225. {
  2226. if (pData->m_dwSuperClassID == dParentId)
  2227. {
  2228. bRet = true;
  2229. break;
  2230. }
  2231. hr = m_CCache.Get(pData->m_dwSuperClassID, &pData);
  2232. }
  2233. return bRet;
  2234. }
  2235. //***************************************************************************
  2236. //
  2237. // CSchemaCache::HasImageProp
  2238. //
  2239. //***************************************************************************
  2240. bool CSchemaCache::HasImageProp (SQL_ID dClassId)
  2241. {
  2242. bool bRet = false;
  2243. _WMILockit lkt(&m_cs);
  2244. ClassData *pData = NULL;
  2245. m_CCache.Get(dClassId, &pData);
  2246. if (pData)
  2247. {
  2248. if (pData->m_dwFlags & REPDRVR_FLAG_IMAGE)
  2249. {
  2250. bRet = true;
  2251. }
  2252. }
  2253. return bRet;
  2254. }
  2255. //***************************************************************************
  2256. //
  2257. // CSchemaCache::Exists
  2258. //
  2259. //***************************************************************************
  2260. BOOL CSchemaCache::Exists (SQL_ID dClassId)
  2261. {
  2262. BOOL bRet = FALSE;
  2263. _WMILockit lkt(&m_cs);
  2264. ClassData *pData = NULL;
  2265. m_CCache.Get(dClassId, &pData);
  2266. if (pData && pData->m_dwDynastyID != 0)
  2267. bRet = TRUE;
  2268. return bRet;
  2269. }
  2270. //***************************************************************************
  2271. //
  2272. // CSchemaCache::DecorateWbemObj
  2273. //
  2274. //***************************************************************************
  2275. HRESULT CSchemaCache::DecorateWbemObj(LPWSTR lpMachineName, LPWSTR lpNamespaceName,
  2276. SQL_ID dScopeId, IWbemClassObject *pTemp, SQL_ID dClassId)
  2277. {
  2278. _IWmiObject *pInt = NULL;
  2279. HRESULT hr = pTemp->QueryInterface(IID__IWmiObject, (void **)&pInt);
  2280. CReleaseMe r (pInt);
  2281. if (pInt)
  2282. {
  2283. wchar_t *pNs = NULL;
  2284. // Decorate this instance. This will let it generate the path.
  2285. // __NAMESPACE
  2286. NamespaceData *pTemp = NULL;
  2287. hr = m_NamespaceIds.Get(dScopeId, &pTemp);
  2288. if (SUCCEEDED(hr) && _wcsicmp(pTemp->m_sNamespaceName, L"root"))
  2289. {
  2290. pNs = new wchar_t [wcslen(lpNamespaceName)+wcslen(pTemp->m_sNamespaceName) + 2];
  2291. if (pNs)
  2292. swprintf(pNs, L"%s\\%s", lpNamespaceName, pTemp->m_sNamespaceName);
  2293. }
  2294. else
  2295. {
  2296. pNs = new wchar_t [wcslen(lpNamespaceName) + 1];
  2297. if (pNs)
  2298. wcscpy(pNs, lpNamespaceName);
  2299. }
  2300. CDeleteMe <wchar_t> d (pNs);
  2301. // Call some method to decorate the object
  2302. hr = pInt->SetDecoration(lpMachineName, pNs);
  2303. }
  2304. return hr;
  2305. }
  2306. //***************************************************************************
  2307. //
  2308. // CSchemaCache::GetKeys
  2309. //
  2310. //***************************************************************************
  2311. HRESULT CSchemaCache::GetKeys(SQL_ID dNsID, LPCWSTR lpClassName, CWStringArray &arrKeys)
  2312. {
  2313. HRESULT hr = WBEM_S_NO_ERROR;
  2314. SQL_ID dClassId;
  2315. hr = GetClassID(lpClassName, dNsID, dClassId);
  2316. if (SUCCEEDED(hr))
  2317. {
  2318. _WMILockit lkt(&m_cs);
  2319. ClassData *pClass = NULL;
  2320. m_CCache.Get(dClassId, &pClass);
  2321. if (!pClass)
  2322. hr = WBEM_E_NOT_FOUND;
  2323. while (pClass)
  2324. {
  2325. for (int i = 0; i < pClass->m_dwNumProps; i++)
  2326. {
  2327. if (pClass->m_Properties[i].m_bIsKey)
  2328. {
  2329. PropertyData *pProp = NULL;
  2330. SQL_ID dTemp = pClass->m_Properties[i].m_dwPropertyId;
  2331. m_Cache.Get(dTemp, &pProp);
  2332. if (pProp)
  2333. arrKeys.Add(pProp->m_sPropertyName);
  2334. }
  2335. }
  2336. SQL_ID dSC = pClass->m_dwSuperClassID;
  2337. pClass = NULL;
  2338. if (!arrKeys.Size() && dSC)
  2339. m_CCache.Get(dSC, &pClass);
  2340. }
  2341. }
  2342. return hr;
  2343. }
  2344. //***************************************************************************
  2345. //
  2346. // CSchemaCache::IsKey
  2347. //
  2348. //***************************************************************************
  2349. BOOL CSchemaCache::IsKey(SQL_ID dClassId, DWORD dwPropID, BOOL &bLocal)
  2350. {
  2351. // Does this property already exist in the hierarchy as a key??
  2352. BOOL bRet = FALSE;
  2353. _WMILockit lkt(&m_cs);
  2354. BOOL bDone = FALSE;
  2355. ClassData *pClass = NULL;
  2356. m_CCache.Get(dClassId, &pClass);
  2357. bLocal = TRUE;
  2358. if (!pClass)
  2359. bRet = FALSE;
  2360. while (pClass)
  2361. {
  2362. for (int i = 0; i < pClass->m_dwNumProps; i++)
  2363. {
  2364. PropertyData *pProp = NULL;
  2365. SQL_ID dTemp = pClass->m_Properties[i].m_dwPropertyId;
  2366. if (dwPropID == dTemp)
  2367. {
  2368. bRet = (pClass->m_Properties[i].m_bIsKey); // Return the first place this ID is defined.
  2369. bDone = TRUE;
  2370. break;
  2371. }
  2372. }
  2373. if (bDone)
  2374. break;
  2375. SQL_ID dSC = pClass->m_dwSuperClassID;
  2376. pClass = NULL;
  2377. if (!bRet && !dSC)
  2378. {
  2379. m_CCache.Get(dSC, &pClass);
  2380. bLocal = FALSE;
  2381. }
  2382. }
  2383. return bRet;
  2384. }
  2385. //***************************************************************************
  2386. //
  2387. // CSchemaCache::SetIsKey
  2388. //
  2389. //***************************************************************************
  2390. HRESULT CSchemaCache::SetIsKey (SQL_ID dClassId, DWORD dwPropID, BOOL bIsKey)
  2391. {
  2392. HRESULT hr = 0;
  2393. BOOL bDone = FALSE;
  2394. _WMILockit lkt(&m_cs);
  2395. ClassData *pClass = NULL;
  2396. m_CCache.Get(dClassId, &pClass);
  2397. if (!pClass)
  2398. hr = WBEM_E_NOT_FOUND;
  2399. else
  2400. pClass->InsertProperty(dwPropID, bIsKey);
  2401. return hr;
  2402. }
  2403. //***************************************************************************
  2404. //
  2405. // CSchemaCache::GetKeyRoot
  2406. //
  2407. //***************************************************************************
  2408. LPWSTR CSchemaCache::GetKeyRoot (LPWSTR lpClassName, SQL_ID dScopeId)
  2409. {
  2410. LPWSTR lpRet = NULL;
  2411. SQL_ID dClassId;
  2412. SQL_ID dRetClass = 0;
  2413. HRESULT hr = GetClassID (lpClassName, dScopeId, dClassId);
  2414. if (SUCCEEDED(hr))
  2415. {
  2416. _WMILockit lkt(&m_cs);
  2417. ClassData *pClass = NULL;
  2418. m_CCache.Get(dClassId, &pClass);
  2419. if (!pClass)
  2420. hr = WBEM_E_NOT_FOUND;
  2421. while (pClass)
  2422. {
  2423. // Find the topmost class that has a key property,
  2424. // or the topmost singleton or unkeyed class.
  2425. if (pClass->m_dwFlags & REPDRVR_FLAG_SINGLETON ||
  2426. pClass->m_dwFlags & REPDRVR_FLAG_UNKEYED)
  2427. {
  2428. dRetClass = pClass->m_dwClassID;
  2429. }
  2430. else
  2431. {
  2432. for (int i = 0; i < pClass->m_dwNumProps; i++)
  2433. {
  2434. if (pClass->m_Properties[i].m_bIsKey)
  2435. {
  2436. dRetClass = pClass->m_dwClassID;
  2437. break;
  2438. }
  2439. }
  2440. }
  2441. SQL_ID dSC = pClass->m_dwSuperClassID;
  2442. pClass = NULL;
  2443. if (dSC)
  2444. m_CCache.Get(dSC, &pClass);
  2445. else
  2446. break;
  2447. }
  2448. if (dRetClass)
  2449. {
  2450. m_CCache.Get(dRetClass, &pClass);
  2451. int iSize = wcslen(pClass->m_sName);
  2452. if (iSize)
  2453. {
  2454. lpRet = new wchar_t [iSize+1];
  2455. if (lpRet)
  2456. wcscpy(lpRet, pClass->m_sName);
  2457. else
  2458. hr = WBEM_E_OUT_OF_MEMORY;
  2459. }
  2460. }
  2461. else
  2462. hr = WBEM_E_NOT_FOUND;
  2463. }
  2464. return lpRet;
  2465. }
  2466. //***************************************************************************
  2467. //
  2468. // CSchemaCache::GetPropertyList
  2469. //
  2470. //***************************************************************************
  2471. HRESULT CSchemaCache::GetPropertyList (SQL_ID dClassId, Properties &pProps, DWORD *pwNumProps)
  2472. {
  2473. HRESULT hr = WBEM_S_NO_ERROR;
  2474. _WMILockit lkt(&m_cs);
  2475. ClassData *pClass = NULL;
  2476. m_CCache.Get(dClassId, &pClass);
  2477. if (pClass)
  2478. {
  2479. for (int i = 0; i < pClass->m_dwNumProps; i++)
  2480. {
  2481. DWORD dwPropertyID = pClass->m_Properties[i].m_dwPropertyId;
  2482. pProps[dwPropertyID] = 0;
  2483. }
  2484. if (pwNumProps)
  2485. *pwNumProps = pClass->m_dwNumProps;
  2486. }
  2487. else
  2488. WBEM_E_NOT_FOUND;
  2489. return hr;
  2490. }
  2491. //***************************************************************************
  2492. //
  2493. // CSchemaCache::ValidateProperty
  2494. //
  2495. //***************************************************************************
  2496. HRESULT CSchemaCache::ValidateProperty (SQL_ID dObjectId, DWORD dwPropertyID, DWORD dwFlags, CIMTYPE cimtype, DWORD dwStorageType,
  2497. LPWSTR lpDefault, BOOL &bChg, BOOL &bIfNoInstances)
  2498. {
  2499. HRESULT hr = WBEM_S_NO_ERROR;
  2500. PropertyData *pData = NULL;
  2501. _WMILockit lkt(&m_cs);
  2502. bChg = TRUE; // We can't tell if the default changed or not, since it ain't cached.
  2503. BOOL bIfNoChildren = FALSE;
  2504. SQL_ID dTemp = dwPropertyID;
  2505. m_Cache.Get(dTemp, &pData);
  2506. if (pData)
  2507. {
  2508. if (pData->m_dwFlags != dwFlags ||
  2509. pData->m_dwCIMType != cimtype)
  2510. bChg = TRUE;
  2511. BOOL bLocal = FALSE;
  2512. BOOL bOldKeyStatus = IsKey(dObjectId, dwPropertyID, bLocal);
  2513. BOOL bNewKeyStatus = ((dwFlags & REPDRVR_FLAG_KEY) ? TRUE : FALSE);
  2514. if (bOldKeyStatus != bNewKeyStatus)
  2515. {
  2516. bIfNoChildren = TRUE;
  2517. bIfNoInstances = TRUE;
  2518. }
  2519. // Check for a legal conversion.
  2520. // We can only change datatypes to larger types of same storage type
  2521. // Except that we can change ints to larger reals.
  2522. if (pData->m_dwCIMType != cimtype)
  2523. {
  2524. if (dwStorageType != pData->m_dwStorageType)
  2525. {
  2526. if (!(pData->m_dwStorageType == WMIDB_STORAGE_NUMERIC &&
  2527. dwStorageType == WMIDB_STORAGE_REAL))
  2528. hr = WBEM_E_INVALID_OPERATION;
  2529. }
  2530. if (SUCCEEDED(hr))
  2531. {
  2532. // Make sure the conversion is to a bigger or same storage unit.
  2533. switch(cimtype)
  2534. {
  2535. case CIM_UINT8:
  2536. case CIM_SINT8:
  2537. switch(pData->m_dwCIMType)
  2538. {
  2539. case CIM_UINT8:
  2540. case CIM_SINT8:
  2541. case CIM_BOOLEAN:
  2542. hr = WBEM_S_NO_ERROR;
  2543. break;
  2544. default:
  2545. hr = WBEM_E_INVALID_OPERATION;
  2546. break;
  2547. }
  2548. break;
  2549. case CIM_UINT16:
  2550. case CIM_SINT16:
  2551. switch(pData->m_dwCIMType)
  2552. {
  2553. case CIM_UINT16:
  2554. case CIM_SINT16:
  2555. case CIM_UINT8:
  2556. case CIM_SINT8:
  2557. case CIM_BOOLEAN:
  2558. hr = WBEM_S_NO_ERROR;
  2559. break;
  2560. default:
  2561. hr = WBEM_E_INVALID_OPERATION;
  2562. break;
  2563. }
  2564. break;
  2565. case CIM_UINT32:
  2566. case CIM_SINT32:
  2567. case CIM_REAL32:
  2568. switch(pData->m_dwCIMType)
  2569. {
  2570. case CIM_UINT32:
  2571. case CIM_SINT32:
  2572. case CIM_UINT16:
  2573. case CIM_SINT16:
  2574. case CIM_UINT8:
  2575. case CIM_SINT8:
  2576. case CIM_BOOLEAN:
  2577. hr = WBEM_S_NO_ERROR;
  2578. break;
  2579. default:
  2580. hr = WBEM_E_INVALID_OPERATION;
  2581. break;
  2582. }
  2583. break;
  2584. case CIM_UINT64:
  2585. case CIM_SINT64:
  2586. switch(pData->m_dwCIMType)
  2587. {
  2588. case CIM_UINT64:
  2589. case CIM_SINT64:
  2590. case CIM_UINT32:
  2591. case CIM_SINT32:
  2592. case CIM_UINT16:
  2593. case CIM_SINT16:
  2594. case CIM_UINT8:
  2595. case CIM_SINT8:
  2596. case CIM_BOOLEAN:
  2597. hr = WBEM_S_NO_ERROR;
  2598. break;
  2599. default:
  2600. hr = WBEM_E_INVALID_OPERATION;
  2601. break;
  2602. }
  2603. break;
  2604. case CIM_REAL64:
  2605. switch(pData->m_dwCIMType)
  2606. {
  2607. case CIM_REAL32:
  2608. case CIM_UINT64:
  2609. case CIM_SINT64:
  2610. case CIM_UINT32:
  2611. case CIM_SINT32:
  2612. case CIM_UINT16:
  2613. case CIM_SINT16:
  2614. case CIM_UINT8:
  2615. case CIM_SINT8:
  2616. case CIM_BOOLEAN:
  2617. hr = WBEM_S_NO_ERROR;
  2618. break;
  2619. default:
  2620. hr = WBEM_E_INVALID_OPERATION;
  2621. break;
  2622. }
  2623. break;
  2624. default:
  2625. hr = WBEM_E_INVALID_OPERATION; // strings, refs, datetimes, etc.
  2626. break;
  2627. }
  2628. }
  2629. }
  2630. if (bIfNoChildren)
  2631. {
  2632. // Fail if we have subclasses.
  2633. SQLIDs ids;
  2634. int iNumChildren = 0;
  2635. hr = GetDerivedClassList(dObjectId, ids, iNumChildren);
  2636. if (SUCCEEDED(hr))
  2637. {
  2638. if (iNumChildren != 0)
  2639. hr = WBEM_E_CLASS_HAS_CHILDREN;
  2640. }
  2641. }
  2642. }
  2643. else
  2644. {
  2645. if (dwFlags & REPDRVR_FLAG_KEY)
  2646. bIfNoInstances = TRUE; // Can't add a key if there are instances.
  2647. }
  2648. return hr;
  2649. }
  2650. //***************************************************************************
  2651. //
  2652. // CSchemaCache::FindProperty
  2653. //
  2654. //***************************************************************************
  2655. HRESULT CSchemaCache::FindProperty(SQL_ID dObjectId, LPWSTR lpPropName, DWORD dwFlags, CIMTYPE ct)
  2656. {
  2657. HRESULT hr = WBEM_S_NO_ERROR;
  2658. // Does this property already exist in a derived class?
  2659. SQLIDs ids;
  2660. int iNumChildren = 0;
  2661. hr = GetDerivedClassList(dObjectId, ids, iNumChildren);
  2662. if (SUCCEEDED(hr))
  2663. {
  2664. for (int i = 0; i < iNumChildren; i++)
  2665. {
  2666. SQL_ID dTemp = ids.at(i);
  2667. DWORD dwTempID = 0;
  2668. if (GetPropertyID(lpPropName, dTemp, dwFlags, ct, dwTempID) == WBEM_S_NO_ERROR)
  2669. {
  2670. hr = WBEM_E_PROPAGATED_PROPERTY;
  2671. break;
  2672. }
  2673. }
  2674. }
  2675. else if (!dObjectId)
  2676. hr = WBEM_S_NO_ERROR;
  2677. return hr;
  2678. }
  2679. //***************************************************************************
  2680. //
  2681. // CSchemaCache::GetDerivedClassList
  2682. //
  2683. //***************************************************************************
  2684. HRESULT CSchemaCache::GetDerivedClassList(SQL_ID dObjectId, SQL_ID **ppIDs,
  2685. int &iNumChildren, BOOL bImmediate)
  2686. {
  2687. HRESULT hr = WBEM_S_NO_ERROR;
  2688. _WMILockit lkt(&m_cs);
  2689. SQLIDs ids;
  2690. hr = GetDerivedClassList(dObjectId, ids, iNumChildren, bImmediate);
  2691. if (SUCCEEDED(hr))
  2692. {
  2693. SQL_ID *pTemp = new SQL_ID [iNumChildren];
  2694. if (pTemp)
  2695. {
  2696. for (int i = 0; i < iNumChildren; i++)
  2697. {
  2698. pTemp[i] = ids.at(i);
  2699. }
  2700. *ppIDs = pTemp;
  2701. }
  2702. else
  2703. hr = WBEM_E_OUT_OF_MEMORY;
  2704. }
  2705. return hr;
  2706. }
  2707. //***************************************************************************
  2708. //
  2709. // CSchemaCache::GetDerivedClassList
  2710. //
  2711. //***************************************************************************
  2712. HRESULT CSchemaCache::GetDerivedClassList(SQL_ID dObjectId, SQLIDs &children,
  2713. int &iNumChildren, BOOL bImmediate)
  2714. {
  2715. HRESULT hr = WBEM_S_NO_ERROR;
  2716. _WMILockit lkt(&m_cs);
  2717. ClassData *pClass = NULL;
  2718. m_CCache.Get(dObjectId, &pClass);
  2719. if (pClass)
  2720. {
  2721. for (int i = 0; i < pClass->m_DerivedIDs.size(); i++)
  2722. {
  2723. SQL_ID dChild = pClass->m_DerivedIDs.at(i);
  2724. children.push_back(dChild);
  2725. iNumChildren++;
  2726. if (!bImmediate)
  2727. hr = GetDerivedClassList(dChild, children, iNumChildren);
  2728. }
  2729. }
  2730. return hr;
  2731. }
  2732. //***************************************************************************
  2733. //
  2734. // CSchemaCache::GetHierarchy
  2735. //
  2736. //***************************************************************************
  2737. HRESULT CSchemaCache::GetHierarchy(SQL_ID dObjectId, SQL_ID **ppIDs, int &iNumIDs)
  2738. {
  2739. HRESULT hr = WBEM_S_NO_ERROR;
  2740. int iSize = 0;
  2741. // Populate the ID list of derived *and* parent class IDs.
  2742. SQLIDs ids;
  2743. hr = GetHierarchy(dObjectId, ids, iNumIDs);
  2744. if (SUCCEEDED(hr))
  2745. {
  2746. SQL_ID *pIDs = new SQL_ID [iNumIDs];
  2747. if (pIDs)
  2748. {
  2749. for (int i = 0; i < iNumIDs; i++)
  2750. {
  2751. pIDs[i] = ids.at(i);
  2752. }
  2753. *ppIDs = pIDs;
  2754. }
  2755. }
  2756. return hr;
  2757. }
  2758. //***************************************************************************
  2759. //
  2760. // CSchemaCache::GetHierarchy
  2761. //
  2762. //***************************************************************************
  2763. HRESULT CSchemaCache::GetHierarchy(SQL_ID dObjectId, SQLIDs &ids, int &iNumIDs)
  2764. {
  2765. HRESULT hr = WBEM_S_NO_ERROR;
  2766. int iSize = 0;
  2767. // Populate the ID list of derived *and* parent class IDs.
  2768. hr = GetDerivedClassList(dObjectId, ids, iNumIDs);
  2769. if (SUCCEEDED(hr))
  2770. {
  2771. SQL_ID dTemp = dObjectId;
  2772. // Load up all the parents.
  2773. while (SUCCEEDED(GetParentId(dTemp, dTemp)))
  2774. {
  2775. ids.push_back(dTemp);
  2776. iNumIDs++;
  2777. }
  2778. }
  2779. return hr;
  2780. }
  2781. //***************************************************************************
  2782. //
  2783. // CSchemaCache::ResizeCache
  2784. //
  2785. //***************************************************************************
  2786. HRESULT CSchemaCache::ResizeCache()
  2787. {
  2788. HRESULT hr = WBEM_S_NO_ERROR;
  2789. _WMILockit lkt(&m_cs);
  2790. SQLIDs ids;
  2791. // Unload an existing dynasty to make room.
  2792. SQLRefCountMap::iterator item = m_DynastiesInUse.begin();
  2793. while (item != m_DynastiesInUse.end())
  2794. {
  2795. if ((*item).second == 0)
  2796. {
  2797. hr = DeleteDynasty((*item).first);
  2798. ids.push_back((*item).first);
  2799. if (m_dwTotalSize < m_dwMaxSize || item == m_DynastiesInUse.end())
  2800. break;
  2801. }
  2802. item++;
  2803. }
  2804. for (int i = 0; i < ids.size(); i++)
  2805. m_DynastiesInUse.erase(m_DynastiesInUse.find(ids.at(i)));
  2806. return hr;
  2807. }
  2808. //***************************************************************************
  2809. //
  2810. // CSchemaCache::LockDynasty
  2811. //
  2812. //***************************************************************************
  2813. HRESULT CSchemaCache::LockDynasty(SQL_ID dDynastyId)
  2814. {
  2815. HRESULT hr = WBEM_S_NO_ERROR;
  2816. ULONG uRefCount = 0;
  2817. _WMILockit lkt(&m_cs);
  2818. SQLRefCountMap::iterator it = m_DynastiesInUse.find(dDynastyId);
  2819. if (it != m_DynastiesInUse.end())
  2820. uRefCount = (*it).second;
  2821. InterlockedIncrement((LONG *) &uRefCount);
  2822. m_DynastiesInUse[dDynastyId] = uRefCount;
  2823. return hr;
  2824. }
  2825. //***************************************************************************
  2826. //
  2827. // CSchemaCache::UnlockDynasty
  2828. //
  2829. //***************************************************************************
  2830. HRESULT CSchemaCache::UnlockDynasty(SQL_ID dDynastyId)
  2831. {
  2832. HRESULT hr = WBEM_S_NO_ERROR;
  2833. _WMILockit lkt(&m_cs);
  2834. ULONG uRefCount = m_DynastiesInUse[dDynastyId];
  2835. InterlockedDecrement((LONG *) &uRefCount);
  2836. m_DynastiesInUse[dDynastyId] = uRefCount;
  2837. return hr;
  2838. }
  2839. //***************************************************************************
  2840. //
  2841. // CSchemaCache::DeleteDynasty
  2842. //
  2843. //***************************************************************************
  2844. HRESULT CSchemaCache::DeleteDynasty(SQL_ID dDynastyId)
  2845. {
  2846. HRESULT hr = WBEM_S_NO_ERROR;
  2847. if (dDynastyId == 1)
  2848. return WBEM_S_NO_ERROR;
  2849. // Delete all class info for members of this dynasty.
  2850. SQLIDs ids;
  2851. int iNum;
  2852. // Immediate only, so we don't inadvertently
  2853. // blow away a protected dynasty.
  2854. hr = GetDerivedClassList(dDynastyId, ids, iNum, TRUE);
  2855. if (SUCCEEDED(hr))
  2856. {
  2857. DeleteClass(dDynastyId);
  2858. for (int i = 0; i < ids.size(); i++)
  2859. {
  2860. SQL_ID d = ids.at(i);
  2861. ULONG uRefCount = 0;
  2862. SQLRefCountMap::iterator it = m_DynastiesInUse.find(d);
  2863. if (it != m_DynastiesInUse.end())
  2864. uRefCount = (*it).second;
  2865. if (!uRefCount)
  2866. hr = DeleteDynasty(d);
  2867. }
  2868. }
  2869. return hr;
  2870. }
  2871. //***************************************************************************
  2872. //
  2873. // CSchemaCache::IsSystemClass
  2874. //
  2875. //***************************************************************************
  2876. BOOL CSchemaCache::IsSystemClass(SQL_ID dObjectId, SQL_ID dClassId)
  2877. {
  2878. BOOL bRet = FALSE;
  2879. _WMILockit lkt(&m_cs);
  2880. HRESULT hr = WBEM_S_NO_ERROR;
  2881. ClassData *pClass = NULL;
  2882. if (dClassId == 1)
  2883. m_CCache.Get(dObjectId, &pClass);
  2884. else
  2885. m_CCache.Get(dClassId, &pClass);
  2886. if (pClass)
  2887. {
  2888. if (pClass->m_sName && pClass->m_sName[0] == L'_')
  2889. bRet = TRUE;
  2890. }
  2891. return bRet;
  2892. }
  2893. //***************************************************************************
  2894. //
  2895. // CSchemaCache::GetWriteToken
  2896. //
  2897. //***************************************************************************
  2898. DWORD CSchemaCache::GetWriteToken(SQL_ID dObjectId, SQL_ID dClassId)
  2899. {
  2900. DWORD dwRet = WBEM_PARTIAL_WRITE_REP;
  2901. BOOL bRet = IsSystemClass(dObjectId, dClassId);
  2902. if (bRet)
  2903. dwRet = WBEM_FULL_WRITE_REP;
  2904. return dwRet;
  2905. }