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.

6236 lines
156 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. --*/
  4. #include <windows.h>
  5. #include <wbemidl.h>
  6. #include <wbemint.h>
  7. #include <stdio.h>
  8. #include <wbemcomn.h>
  9. #include <ql.h>
  10. #include <time.h>
  11. #include "a51rep.h"
  12. #include <md5.h>
  13. #include <objpath.h>
  14. #include "lock.h"
  15. #include <persistcfg.h>
  16. #include "a51fib.h"
  17. #include "RepositoryPackager.h"
  18. //**************************************************************************************************
  19. HRESULT STDMETHODCALLTYPE CSession::QueryInterface(REFIID riid, void** ppv)
  20. {
  21. if(riid == IID_IUnknown || riid == IID_IWmiDbSession ||
  22. riid == IID_IWmiDbSessionEx)
  23. {
  24. AddRef();
  25. *ppv = this;
  26. return S_OK;
  27. }
  28. else return E_NOINTERFACE;
  29. }
  30. ULONG STDMETHODCALLTYPE CSession::Release()
  31. {
  32. return CUnkBase<IWmiDbSessionEx, &IID_IWmiDbSessionEx>::Release();
  33. }
  34. CSession::~CSession()
  35. {
  36. }
  37. HRESULT STDMETHODCALLTYPE CSession::GetObject(
  38. IWmiDbHandle *pScope,
  39. IWbemPath *pPath,
  40. DWORD dwFlags,
  41. DWORD dwRequestedHandleType,
  42. IWmiDbHandle **ppResult
  43. )
  44. {
  45. #ifdef A51_SUPER_VERBOSE_LOGGING
  46. {
  47. DWORD dwLen = 0;
  48. HRESULT hres = pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, NULL);
  49. if(FAILED(hres) && hres != WBEM_E_BUFFER_TOO_SMALL)
  50. return hres;
  51. WCHAR* wszBuffer = (WCHAR*)TempAlloc(dwLen * sizeof(WCHAR));
  52. if(wszBuffer == NULL)
  53. return WBEM_E_OUT_OF_MEMORY;
  54. CTempFreeMe tfm(wszBuffer, dwLen * sizeof(WCHAR));
  55. if(FAILED(pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, wszBuffer)))
  56. return WBEM_E_FAILED;
  57. ERRORTRACE((LOG_REPDRV, "CSession::GetObject - pPath=<%S>\n", wszBuffer));
  58. }
  59. #endif
  60. try
  61. {
  62. HRESULT hres;
  63. CAutoReadLock lock(&g_readWriteLock);
  64. if (!m_bInWriteTransaction)
  65. {
  66. if (!lock.Lock())
  67. return WBEM_E_FAILED;
  68. }
  69. if (g_bShuttingDown)
  70. {
  71. return WBEM_E_SHUTTING_DOWN;
  72. }
  73. CNamespaceHandle* pNs = (CNamespaceHandle*)pScope;
  74. if(FAILED(pNs->GetErrorStatus()))
  75. {
  76. return pNs->GetErrorStatus();
  77. }
  78. hres = pNs->GetObject(pPath, dwFlags, dwRequestedHandleType,
  79. ppResult);
  80. InternalCommitTransaction(false);
  81. return hres;
  82. }
  83. catch (...)
  84. {
  85. return WBEM_E_CRITICAL_ERROR;
  86. }
  87. }
  88. HRESULT STDMETHODCALLTYPE CSession::GetObjectDirect(
  89. IWmiDbHandle *pScope,
  90. IWbemPath *pPath,
  91. DWORD dwFlags,
  92. REFIID riid,
  93. LPVOID *pObj
  94. )
  95. {
  96. #ifdef A51_SUPER_VERBOSE_LOGGING
  97. {
  98. DWORD dwLen = 0;
  99. HRESULT hres = pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, NULL);
  100. if(FAILED(hres) && hres != WBEM_E_BUFFER_TOO_SMALL)
  101. return hres;
  102. WCHAR* wszBuffer = (WCHAR*)TempAlloc(dwLen * sizeof(WCHAR));
  103. if(wszBuffer == NULL)
  104. return WBEM_E_OUT_OF_MEMORY;
  105. CTempFreeMe tfm(wszBuffer, dwLen * sizeof(WCHAR));
  106. if(FAILED(pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, wszBuffer)))
  107. return WBEM_E_FAILED;
  108. ERRORTRACE((LOG_REPDRV, "CSession::GetObjectDirect - pPath=<%S>\n", wszBuffer));
  109. }
  110. #endif
  111. try
  112. {
  113. HRESULT hres;
  114. CAutoReadLock lock(&g_readWriteLock);
  115. if (!m_bInWriteTransaction)
  116. {
  117. if (!lock.Lock())
  118. return WBEM_E_FAILED;
  119. }
  120. if (g_bShuttingDown)
  121. return WBEM_E_SHUTTING_DOWN;
  122. CNamespaceHandle* pNs = (CNamespaceHandle*)pScope;
  123. if(FAILED(pNs->GetErrorStatus()))
  124. {
  125. return pNs->GetErrorStatus();
  126. }
  127. hres = pNs->GetObjectDirect(pPath, dwFlags, riid, pObj);
  128. InternalCommitTransaction(false);
  129. return hres;
  130. }
  131. catch (...)
  132. {
  133. return WBEM_E_CRITICAL_ERROR;
  134. }
  135. }
  136. HRESULT STDMETHODCALLTYPE CSession::GetObjectByPath(
  137. IWmiDbHandle *pScope,
  138. LPCWSTR wszObjectPath,
  139. DWORD dwFlags,
  140. REFIID riid,
  141. LPVOID *pObj
  142. )
  143. {
  144. #ifdef A51_SUPER_VERBOSE_LOGGING
  145. {
  146. ERRORTRACE((LOG_REPDRV, "CSession::GetObjectByPath - pPath=<%S>\n", wszObjectPath));
  147. }
  148. #endif
  149. try
  150. {
  151. HRESULT hres;
  152. CAutoReadLock lock(&g_readWriteLock);
  153. if (!m_bInWriteTransaction)
  154. {
  155. if (!lock.Lock())
  156. return WBEM_E_FAILED;
  157. }
  158. if (g_bShuttingDown)
  159. return WBEM_E_SHUTTING_DOWN;
  160. CNamespaceHandle* pNs = (CNamespaceHandle*)pScope;
  161. if(FAILED(pNs->GetErrorStatus()))
  162. {
  163. return pNs->GetErrorStatus();
  164. }
  165. DWORD dwLen = wcslen(wszObjectPath)+1;
  166. LPWSTR wszPath = (WCHAR*)TempAlloc(dwLen*sizeof(WCHAR));
  167. if (wszPath == NULL)
  168. {
  169. return WBEM_E_OUT_OF_MEMORY;
  170. }
  171. wcscpy(wszPath, wszObjectPath);
  172. CTempFreeMe vdm(wszPath, dwLen * sizeof(WCHAR));
  173. hres = pNs->GetObjectByPath(wszPath, dwFlags, riid, pObj);
  174. InternalCommitTransaction(false);
  175. return hres;
  176. }
  177. catch (...)
  178. {
  179. return WBEM_E_CRITICAL_ERROR;
  180. }
  181. }
  182. HRESULT STDMETHODCALLTYPE CSession::PutObject(
  183. IWmiDbHandle *pScope,
  184. REFIID riid,
  185. LPVOID pObj,
  186. DWORD dwFlags,
  187. DWORD dwRequestedHandleType,
  188. IWmiDbHandle **ppResult
  189. )
  190. {
  191. #ifdef A51_SUPER_VERBOSE_LOGGING
  192. {
  193. _IWmiObject* pObjEx = NULL;
  194. ((IUnknown*)pObj)->QueryInterface(IID__IWmiObject, (void**)&pObjEx);
  195. CReleaseMe rm1(pObjEx);
  196. BSTR str = NULL;
  197. pObjEx->GetObjectText(0, &str);
  198. CSysFreeMe sfm( str );
  199. ERRORTRACE((LOG_REPDRV, "CSession::PutObject Flags = <0x%X> - <%S>\n", dwFlags, str));
  200. }
  201. #endif
  202. try
  203. {
  204. HRESULT hres;
  205. long lRes;
  206. CAutoWriteLock lock(&g_readWriteLock);
  207. CEventCollector aNonTransactedEvents;
  208. CEventCollector *aEvents = &m_aTransactedEvents;
  209. if (!m_bInWriteTransaction)
  210. {
  211. if (!lock.Lock())
  212. return WBEM_E_FAILED;
  213. if (g_bShuttingDown)
  214. return WBEM_E_SHUTTING_DOWN;
  215. aEvents = &aNonTransactedEvents;
  216. hres = InternalBeginTransaction(true);
  217. if(hres != ERROR_SUCCESS)
  218. return hres;
  219. g_Glob.GetForestCache()->BeginTransaction();
  220. }
  221. else if (g_bShuttingDown)
  222. return WBEM_E_SHUTTING_DOWN;
  223. CNamespaceHandle* pNs = (CNamespaceHandle*)pScope;
  224. if(FAILED(pNs->GetErrorStatus()))
  225. {
  226. if(!m_bInWriteTransaction)
  227. {
  228. InternalAbortTransaction(true);
  229. g_Glob.GetForestCache()->AbortTransaction();
  230. }
  231. return pNs->GetErrorStatus();
  232. }
  233. hres = pNs->PutObject(riid, pObj, dwFlags, dwRequestedHandleType, ppResult, *aEvents);
  234. if(!m_bInWriteTransaction)
  235. {
  236. if (FAILED(hres))
  237. {
  238. InternalAbortTransaction(true);
  239. g_Glob.GetForestCache()->AbortTransaction();
  240. }
  241. else
  242. {
  243. hres = InternalCommitTransaction(true);
  244. if(hres != ERROR_SUCCESS)
  245. {
  246. g_Glob.GetForestCache()->AbortTransaction();
  247. }
  248. else
  249. {
  250. g_Glob.GetForestCache()->CommitTransaction();
  251. lock.Unlock();
  252. _IWmiCoreServices * pSvcs = g_Glob.GetCoreSvcs();
  253. CReleaseMe rm(pSvcs);
  254. aNonTransactedEvents.SendEvents(pSvcs);
  255. }
  256. }
  257. aNonTransactedEvents.DeleteAllEvents();
  258. }
  259. return hres;
  260. }
  261. catch (...)
  262. {
  263. return WBEM_E_CRITICAL_ERROR;
  264. }
  265. }
  266. HRESULT STDMETHODCALLTYPE CSession::DeleteObject(
  267. IWmiDbHandle *pScope,
  268. DWORD dwFlags,
  269. REFIID riid,
  270. LPVOID pObj
  271. )
  272. {
  273. #ifdef A51_SUPER_VERBOSE_LOGGING
  274. {
  275. _IWmiObject* pObjEx = NULL;
  276. ((IUnknown*)pObj)->QueryInterface(IID__IWmiObject, (void**)&pObjEx);
  277. CReleaseMe rm1(pObjEx);
  278. BSTR str = NULL;
  279. pObjEx->GetObjectText(0, &str);
  280. CSysFreeMe sfm( str );
  281. ERRORTRACE((LOG_REPDRV, "CSession::DeleteObject - <%S>\n", str));
  282. }
  283. #endif
  284. try
  285. {
  286. HRESULT hres;
  287. long lRes;
  288. CAutoWriteLock lock(&g_readWriteLock);
  289. CEventCollector aNonTransactedEvents;
  290. CEventCollector *aEvents = &m_aTransactedEvents;
  291. if (!m_bInWriteTransaction)
  292. {
  293. if (!lock.Lock())
  294. return WBEM_E_FAILED;
  295. if (g_bShuttingDown)
  296. return WBEM_E_SHUTTING_DOWN;
  297. aEvents = &aNonTransactedEvents;
  298. hres = InternalBeginTransaction(true);
  299. if(hres != ERROR_SUCCESS)
  300. return hres;
  301. }
  302. else if (g_bShuttingDown)
  303. return WBEM_E_SHUTTING_DOWN;
  304. CNamespaceHandle* pNs = (CNamespaceHandle*)pScope;
  305. if(FAILED(pNs->GetErrorStatus()))
  306. {
  307. if(!m_bInWriteTransaction)
  308. {
  309. InternalAbortTransaction(true);
  310. }
  311. return pNs->GetErrorStatus();
  312. }
  313. hres = pNs->DeleteObject(dwFlags, riid, pObj, *aEvents);
  314. if(!m_bInWriteTransaction)
  315. {
  316. if (FAILED(hres))
  317. {
  318. InternalAbortTransaction(true);
  319. }
  320. else
  321. {
  322. hres = InternalCommitTransaction(true);
  323. if(hres == ERROR_SUCCESS)
  324. {
  325. lock.Unlock();
  326. _IWmiCoreServices * pSvcs = g_Glob.GetCoreSvcs();
  327. CReleaseMe rm(pSvcs);
  328. aNonTransactedEvents.SendEvents(pSvcs);
  329. }
  330. }
  331. aNonTransactedEvents.DeleteAllEvents();
  332. }
  333. return hres;
  334. }
  335. catch (...)
  336. {
  337. return WBEM_E_CRITICAL_ERROR;
  338. }
  339. }
  340. HRESULT STDMETHODCALLTYPE CSession::DeleteObjectByPath(
  341. IWmiDbHandle *pScope,
  342. LPCWSTR wszObjectPath,
  343. DWORD dwFlags
  344. )
  345. {
  346. #ifdef A51_SUPER_VERBOSE_LOGGING
  347. {
  348. ERRORTRACE((LOG_REPDRV, "CSession::DeleteObjectByPath - <%S>\n", wszObjectPath));
  349. }
  350. #endif
  351. try
  352. {
  353. HRESULT hres;
  354. long lRes;
  355. CAutoWriteLock lock(&g_readWriteLock);
  356. CEventCollector aNonTransactedEvents;
  357. CEventCollector *aEvents = &m_aTransactedEvents;
  358. if (!m_bInWriteTransaction)
  359. {
  360. if (!lock.Lock())
  361. return WBEM_E_FAILED;
  362. if (g_bShuttingDown)
  363. return WBEM_E_SHUTTING_DOWN;
  364. aEvents = &aNonTransactedEvents;
  365. hres = InternalBeginTransaction(true);
  366. if(hres != ERROR_SUCCESS)
  367. return hres;
  368. }
  369. else if (g_bShuttingDown)
  370. return WBEM_E_SHUTTING_DOWN;
  371. CNamespaceHandle* pNs = (CNamespaceHandle*)pScope;
  372. if(FAILED(pNs->GetErrorStatus()))
  373. {
  374. if(!m_bInWriteTransaction)
  375. {
  376. InternalAbortTransaction(true);
  377. }
  378. return pNs->GetErrorStatus();
  379. }
  380. DWORD dwLen = wcslen(wszObjectPath)+1;
  381. LPWSTR wszPath = (WCHAR*)TempAlloc(dwLen*sizeof(WCHAR));
  382. if (wszPath == NULL)
  383. {
  384. if(!m_bInWriteTransaction)
  385. {
  386. InternalAbortTransaction(true);
  387. }
  388. return WBEM_E_OUT_OF_MEMORY;
  389. }
  390. wcscpy(wszPath, wszObjectPath);
  391. CTempFreeMe vdm(wszPath, dwLen * sizeof(WCHAR));
  392. hres = pNs->DeleteObjectByPath(dwFlags, wszPath, *aEvents);
  393. if(!m_bInWriteTransaction)
  394. {
  395. if (FAILED(hres))
  396. {
  397. InternalAbortTransaction(true);
  398. }
  399. else
  400. {
  401. hres = InternalCommitTransaction(true);
  402. if(hres == ERROR_SUCCESS)
  403. {
  404. lock.Unlock();
  405. _IWmiCoreServices * pSvcs = g_Glob.GetCoreSvcs();
  406. CReleaseMe rm(pSvcs);
  407. aNonTransactedEvents.SendEvents(pSvcs);
  408. }
  409. }
  410. aNonTransactedEvents.DeleteAllEvents();
  411. }
  412. return hres;
  413. }
  414. catch (...)
  415. {
  416. return WBEM_E_CRITICAL_ERROR;
  417. }
  418. }
  419. HRESULT STDMETHODCALLTYPE CSession::ExecQuery(
  420. IWmiDbHandle *pScope,
  421. IWbemQuery *pQuery,
  422. DWORD dwFlags,
  423. DWORD dwRequestedHandleType,
  424. DWORD *dwMessageFlags,
  425. IWmiDbIterator **ppQueryResult
  426. )
  427. {
  428. #ifdef A51_SUPER_VERBOSE_LOGGING
  429. {
  430. LPWSTR wszQuery = NULL;
  431. HRESULT hres = pQuery->GetAnalysis(WMIQ_ANALYSIS_QUERY_TEXT, 0, (void**)&wszQuery);
  432. if (FAILED(hres))
  433. return hres;
  434. ERRORTRACE((LOG_REPDRV, "CSession::ExecQuery - <%S>\n", wszQuery));
  435. pQuery->FreeMemory(wszQuery);
  436. }
  437. #endif
  438. try
  439. {
  440. HRESULT hres;
  441. CAutoReadLock lock(&g_readWriteLock);
  442. if (!m_bInWriteTransaction)
  443. {
  444. if (!lock.Lock())
  445. return WBEM_E_FAILED;
  446. }
  447. if (g_bShuttingDown)
  448. return WBEM_E_SHUTTING_DOWN;
  449. CNamespaceHandle* pNs = (CNamespaceHandle*)pScope;
  450. if(FAILED(pNs->GetErrorStatus()))
  451. {
  452. return pNs->GetErrorStatus();
  453. }
  454. //If we are in a transaction, we have to get a message to the iteratir
  455. //on create so it does not mess around with the locks!
  456. if (m_bInWriteTransaction)
  457. pNs->TellIteratorNotToLock();
  458. hres = pNs->ExecQuery(pQuery, dwFlags,
  459. dwRequestedHandleType, dwMessageFlags, ppQueryResult);
  460. InternalCommitTransaction(false);
  461. return hres;
  462. }
  463. catch (...)
  464. {
  465. return WBEM_E_CRITICAL_ERROR;
  466. }
  467. }
  468. HRESULT STDMETHODCALLTYPE CSession::ExecQuerySink(
  469. IWmiDbHandle *pScope,
  470. IWbemQuery *pQuery,
  471. DWORD dwFlags,
  472. DWORD dwRequestedHandleType,
  473. IWbemObjectSink* pSink,
  474. DWORD *dwMessageFlags
  475. )
  476. {
  477. try
  478. {
  479. HRESULT hres;
  480. CAutoReadLock lock(&g_readWriteLock);
  481. if (!m_bInWriteTransaction)
  482. {
  483. if (!lock.Lock())
  484. return WBEM_E_FAILED;
  485. }
  486. if (g_bShuttingDown)
  487. return WBEM_E_SHUTTING_DOWN;
  488. CNamespaceHandle* pNs = (CNamespaceHandle*)pScope;
  489. if(FAILED(pNs->GetErrorStatus()))
  490. {
  491. return pNs->GetErrorStatus();
  492. }
  493. hres = pNs->ExecQuerySink(pQuery, dwFlags,
  494. dwRequestedHandleType, pSink, dwMessageFlags);
  495. InternalCommitTransaction(false);
  496. return hres;
  497. }
  498. catch (...)
  499. {
  500. return WBEM_E_CRITICAL_ERROR;
  501. }
  502. }
  503. HRESULT STDMETHODCALLTYPE CSession::RenameObject(
  504. IWbemPath *pOldPath,
  505. IWbemPath *pNewPath,
  506. DWORD dwFlags,
  507. DWORD dwRequestedHandleType,
  508. IWmiDbHandle **ppResult
  509. )
  510. {
  511. DebugBreak();
  512. return E_NOTIMPL;
  513. }
  514. HRESULT STDMETHODCALLTYPE CSession::Enumerate(
  515. IWmiDbHandle *pScope,
  516. DWORD dwFlags,
  517. DWORD dwRequestedHandleType,
  518. IWmiDbIterator **ppQueryResult
  519. )
  520. {
  521. DebugBreak();
  522. return E_NOTIMPL;
  523. }
  524. HRESULT STDMETHODCALLTYPE CSession::AddObject(
  525. IWmiDbHandle *pScope,
  526. IWbemPath *pPath,
  527. DWORD dwFlags,
  528. DWORD dwRequestedHandleType,
  529. IWmiDbHandle **ppResult
  530. )
  531. {
  532. DebugBreak();
  533. return E_NOTIMPL;
  534. }
  535. HRESULT STDMETHODCALLTYPE CSession::RemoveObject (
  536. IWmiDbHandle *pScope,
  537. IWbemPath *pPath,
  538. DWORD dwFlags
  539. )
  540. {
  541. DebugBreak();
  542. return E_NOTIMPL;
  543. }
  544. HRESULT STDMETHODCALLTYPE CSession::SetDecoration(
  545. LPWSTR lpMachineName,
  546. LPWSTR lpNamespacePath
  547. )
  548. {
  549. //
  550. // As the default driver, we really don't care.
  551. //
  552. return WBEM_S_NO_ERROR;
  553. }
  554. HRESULT STDMETHODCALLTYPE CSession::BeginWriteTransaction(DWORD dwFlags)
  555. {
  556. if (CLock::NoError != g_readWriteLock.WriteLock())
  557. return WBEM_E_FAILED;
  558. if (g_bShuttingDown)
  559. {
  560. g_readWriteLock.WriteUnlock();
  561. return WBEM_E_SHUTTING_DOWN;
  562. }
  563. HRESULT hres = InternalBeginTransaction(true);
  564. if(hres != ERROR_SUCCESS)
  565. {
  566. g_readWriteLock.WriteUnlock();
  567. return hres;
  568. }
  569. m_bInWriteTransaction = true;
  570. return ERROR_SUCCESS;
  571. }
  572. HRESULT STDMETHODCALLTYPE CSession::BeginReadTransaction(DWORD dwFlags)
  573. {
  574. if (CLock::NoError != g_readWriteLock.ReadLock())
  575. return WBEM_E_FAILED;
  576. if (g_bShuttingDown)
  577. {
  578. g_readWriteLock.ReadUnlock();
  579. return WBEM_E_SHUTTING_DOWN;
  580. }
  581. return ERROR_SUCCESS;
  582. }
  583. HRESULT STDMETHODCALLTYPE CSession::CommitTransaction(DWORD dwFlags)
  584. {
  585. if (m_bInWriteTransaction)
  586. {
  587. long lRes = g_Glob.GetFileCache()->CommitTransaction();
  588. if(lRes != ERROR_SUCCESS)
  589. {
  590. HRESULT hres = A51TranslateErrorCode(lRes);
  591. AbortTransaction(0);
  592. CRepository::RecoverCheckpoint();
  593. return hres;
  594. }
  595. else
  596. {
  597. CRepository::WriteOperationNotification();
  598. }
  599. m_bInWriteTransaction = false;
  600. //Copy the event list and delete the original. We need to deliver
  601. //outside the write lock.
  602. CEventCollector aTransactedEvents;
  603. aTransactedEvents.TransferEvents(m_aTransactedEvents);
  604. g_readWriteLock.WriteUnlock();
  605. _IWmiCoreServices * pSvcs = g_Glob.GetCoreSvcs();
  606. CReleaseMe rm(pSvcs);
  607. aTransactedEvents.SendEvents(pSvcs);
  608. aTransactedEvents.DeleteAllEvents();
  609. }
  610. else
  611. {
  612. if (m_aTransactedEvents.GetSize())
  613. {
  614. _ASSERT(false, L"Read transaction has events to send");
  615. }
  616. g_readWriteLock.ReadUnlock();
  617. }
  618. return ERROR_SUCCESS;
  619. }
  620. HRESULT STDMETHODCALLTYPE CSession::AbortTransaction(DWORD dwFlags)
  621. {
  622. if (m_bInWriteTransaction)
  623. {
  624. m_bInWriteTransaction = false;
  625. g_Glob.GetFileCache()->AbortTransaction();
  626. m_aTransactedEvents.DeleteAllEvents();
  627. g_readWriteLock.WriteUnlock();
  628. }
  629. else
  630. {
  631. if (m_aTransactedEvents.GetSize())
  632. {
  633. _ASSERT(false, L"Read transaction has events to send");
  634. }
  635. g_readWriteLock.ReadUnlock();
  636. }
  637. return ERROR_SUCCESS;
  638. }
  639. HRESULT CSession::InternalBeginTransaction(bool bWriteOperation)
  640. {
  641. if (bWriteOperation)
  642. {
  643. long lRes = g_Glob.GetFileCache()->BeginTransaction();
  644. if (lRes)
  645. {
  646. //An internal error state may have been triggered, therefore
  647. //we should try and recover from that and try again...
  648. CRepository::RecoverCheckpoint();
  649. lRes = g_Glob.GetFileCache()->BeginTransaction();
  650. }
  651. return A51TranslateErrorCode(lRes);
  652. }
  653. else
  654. return ERROR_SUCCESS;
  655. }
  656. HRESULT CSession::InternalAbortTransaction(bool bWriteOperation)
  657. {
  658. if (bWriteOperation)
  659. {
  660. g_Glob.GetFileCache()->AbortTransaction();
  661. }
  662. return ERROR_SUCCESS;
  663. }
  664. HRESULT CSession::InternalCommitTransaction(bool bWriteOperation)
  665. {
  666. DWORD dwres = ERROR_SUCCESS;
  667. if (bWriteOperation)
  668. {
  669. long lRes = g_Glob.GetFileCache()->CommitTransaction();
  670. if(lRes != ERROR_SUCCESS)
  671. {
  672. dwres = A51TranslateErrorCode(lRes);
  673. InternalAbortTransaction(bWriteOperation);
  674. CRepository::RecoverCheckpoint();
  675. }
  676. else
  677. {
  678. CRepository::WriteOperationNotification();
  679. }
  680. }
  681. else
  682. {
  683. CRepository::ReadOperationNotification();
  684. }
  685. return dwres;
  686. }
  687. //
  688. //
  689. //
  690. //
  691. ///////////////////////////////////////////////////////////////////////
  692. long CNamespaceHandle::s_lActiveRepNs = 0;
  693. CNamespaceHandle::CNamespaceHandle(CLifeControl* pControl,CRepository * pRepository)
  694. : TUnkBase(pControl), m_pClassCache(NULL),
  695. m_pNullClass(NULL), m_bCached(false), m_pRepository(pRepository),
  696. m_bUseIteratorLock(true)
  697. {
  698. m_pRepository->AddRef();
  699. // unrefed pointer to a global
  700. m_ForestCache = g_Glob.GetForestCache();
  701. InterlockedIncrement(&s_lActiveRepNs);
  702. }
  703. CNamespaceHandle::~CNamespaceHandle()
  704. {
  705. if(m_pClassCache)
  706. {
  707. // give-up our own reference
  708. // m_pClassCache->Release();
  709. // remove from the Forest cache this namespace
  710. m_ForestCache->ReleaseNamespaceCache(m_wsNamespace, m_pClassCache);
  711. }
  712. m_pRepository->Release();
  713. if(m_pNullClass)
  714. m_pNullClass->Release();
  715. InterlockedDecrement(&s_lActiveRepNs);
  716. }
  717. CHR CNamespaceHandle::GetErrorStatus()
  718. {
  719. //
  720. // TEMP CODE: Someone is calling us on an impersonated thread. Let's catch
  721. // the, ahem, culprit
  722. //
  723. HANDLE hToken;
  724. BOOL bRes = OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken);
  725. if(bRes)
  726. {
  727. //_ASSERT(false, L"Called with a thread token");
  728. ERRORTRACE((LOG_WBEMCORE, "Repository called with a thread token! "
  729. "It shall be removed\n"));
  730. CloseHandle(hToken);
  731. SetThreadToken(NULL, NULL);
  732. }
  733. return m_pClassCache->GetError();
  734. }
  735. void CNamespaceHandle::SetErrorStatus(HRESULT hres)
  736. {
  737. m_pClassCache->SetError(hres);
  738. }
  739. CHR CNamespaceHandle::Initialize(LPCWSTR wszNamespace, LPCWSTR wszScope)
  740. {
  741. HRESULT hres;
  742. m_wsNamespace = wszNamespace;
  743. m_wsFullNamespace = L"\\\\.\\";
  744. m_wsFullNamespace += wszNamespace;
  745. DWORD dwSize = MAX_COMPUTERNAME_LENGTH+1;
  746. GetComputerNameW(m_wszMachineName, &dwSize);
  747. if(wszScope)
  748. m_wsScope = wszScope;
  749. //
  750. // Ask the forest for the cache for this namespace
  751. //
  752. m_pClassCache = g_Glob.GetForestCache()->
  753. GetNamespaceCache(wszNamespace);
  754. if(m_pClassCache == NULL)
  755. return WBEM_E_OUT_OF_MEMORY;
  756. wcscpy(m_wszClassRootDir, g_Glob.GetRootDir());
  757. //
  758. // Append namespace-specific prefix
  759. //
  760. wcscat(m_wszClassRootDir, L"\\NS_");
  761. //
  762. // Append hashed namespace name
  763. //
  764. if (!Hash(wszNamespace, m_wszClassRootDir + wcslen(m_wszClassRootDir)))
  765. return WBEM_E_OUT_OF_MEMORY;
  766. m_lClassRootDirLen = wcslen(m_wszClassRootDir);
  767. //
  768. // Constuct the instance root dir
  769. //
  770. if(wszScope == NULL)
  771. {
  772. //
  773. // Basic namespace --- instances go into the root of the namespace
  774. //
  775. wcscpy(m_wszInstanceRootDir, m_wszClassRootDir);
  776. m_lInstanceRootDirLen = m_lClassRootDirLen;
  777. }
  778. else
  779. {
  780. wcscpy(m_wszInstanceRootDir, m_wszClassRootDir);
  781. wcscat(m_wszInstanceRootDir, L"\\" A51_SCOPE_DIR_PREFIX);
  782. if(!Hash(m_wsScope,
  783. m_wszInstanceRootDir + wcslen(m_wszInstanceRootDir)))
  784. {
  785. return WBEM_E_OUT_OF_MEMORY;
  786. }
  787. m_lInstanceRootDirLen = wcslen(m_wszInstanceRootDir);
  788. }
  789. return WBEM_S_NO_ERROR;
  790. }
  791. CHR CNamespaceHandle::GetObject(
  792. IWbemPath *pPath,
  793. DWORD dwFlags,
  794. DWORD dwRequestedHandleType,
  795. IWmiDbHandle **ppResult
  796. )
  797. {
  798. HRESULT hres;
  799. if((dwRequestedHandleType & WMIDB_HANDLE_TYPE_COOKIE) == 0)
  800. {
  801. DebugBreak();
  802. return E_NOTIMPL;
  803. }
  804. DWORD dwLen = 0;
  805. hres = pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, NULL);
  806. if(FAILED(hres) && hres != WBEM_E_BUFFER_TOO_SMALL)
  807. return hres;
  808. WCHAR* wszBuffer = (WCHAR*)TempAlloc(dwLen * sizeof(WCHAR));
  809. if(wszBuffer == NULL)
  810. return WBEM_E_OUT_OF_MEMORY;
  811. CTempFreeMe tfm(wszBuffer, dwLen * sizeof(WCHAR));
  812. if(FAILED(pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, wszBuffer)))
  813. return WBEM_E_FAILED;
  814. return GetObjectHandleByPath(wszBuffer, dwFlags, dwRequestedHandleType,
  815. ppResult);
  816. }
  817. CHR CNamespaceHandle::GetObjectHandleByPath(
  818. LPWSTR wszBuffer,
  819. DWORD dwFlags,
  820. DWORD dwRequestedHandleType,
  821. IWmiDbHandle **ppResult
  822. )
  823. {
  824. //
  825. // Get the key from path
  826. //
  827. DWORD dwLen = wcslen(wszBuffer)*sizeof(WCHAR)+2;
  828. LPWSTR wszKey = (WCHAR*)TempAlloc(dwLen);
  829. if(wszKey == NULL)
  830. return WBEM_E_OUT_OF_MEMORY;
  831. CTempFreeMe tfm(wszKey, dwLen);
  832. bool bIsClass;
  833. LPWSTR wszClassName = NULL;
  834. HRESULT hres = ComputeKeyFromPath(wszBuffer, wszKey, &wszClassName,
  835. &bIsClass);
  836. if(FAILED(hres))
  837. return hres;
  838. CTempFreeMe tfm1(wszClassName, (wcslen(wszClassName)+1) * sizeof(WCHAR*));
  839. //
  840. // Check if it exists (except for ROOT --- it's fake)
  841. //
  842. _IWmiObject* pObj = NULL;
  843. if(m_wsNamespace.Length() > 0)
  844. {
  845. hres = GetInstanceByKey(wszClassName, wszKey, IID__IWmiObject,
  846. (void**)&pObj);
  847. if(FAILED(hres))
  848. return hres;
  849. }
  850. CReleaseMe rm1(pObj);
  851. CNamespaceHandle* pNewHandle = new CNamespaceHandle(m_pControl,m_pRepository);
  852. if (pNewHandle == NULL)
  853. return WBEM_E_OUT_OF_MEMORY;
  854. pNewHandle->AddRef();
  855. CReleaseMe rm2(pNewHandle);
  856. //
  857. // Check if this is a namespace or not
  858. //
  859. if(pObj == NULL || pObj->InheritsFrom(L"__Namespace") == S_OK)
  860. {
  861. //
  862. // It's a namespace. Open a basic handle pointing to it
  863. //
  864. WString wsName = m_wsNamespace;
  865. if(wsName.Length() > 0)
  866. wsName += L"\\";
  867. wsName += wszKey;
  868. hres = pNewHandle->Initialize(wsName);
  869. //
  870. // Since our namespace is for real, tell the cache that it is now valid.
  871. // The cache might have been invalidated if this namespace was deleted
  872. // in the past
  873. //
  874. if (SUCCEEDED(hres))
  875. pNewHandle->SetErrorStatus(S_OK);
  876. }
  877. else
  878. {
  879. //
  880. // It's a scope. Construct the new scope name by appending this
  881. // object's path to our own scope
  882. //
  883. VARIANT v;
  884. VariantInit(&v);
  885. CClearMe cm(&v);
  886. hres = pObj->Get(L"__RELPATH", 0, &v, NULL, NULL);
  887. if(FAILED(hres))
  888. return hres;
  889. if(V_VT(&v) != VT_BSTR)
  890. return WBEM_E_INVALID_OBJECT;
  891. WString wsScope = m_wsScope;
  892. if(wsScope.Length() > 0)
  893. wsScope += L":";
  894. wsScope += V_BSTR(&v);
  895. hres = pNewHandle->Initialize(m_wsNamespace, wsScope);
  896. }
  897. if(FAILED(hres))
  898. return hres;
  899. return pNewHandle->QueryInterface(IID_IWmiDbHandle, (void**)ppResult);
  900. }
  901. CHR CNamespaceHandle::ComputeKeyFromPath(LPWSTR wszPath, LPWSTR wszKey,
  902. TEMPFREE_ME LPWSTR* pwszClass,
  903. bool* pbIsClass,
  904. TEMPFREE_ME LPWSTR* pwszNamespace)
  905. {
  906. HRESULT hres;
  907. *pbIsClass = false;
  908. //
  909. // Get and skip the namespace portion.
  910. //
  911. if(wszPath[0] == '\\' || wszPath[0] == '/')
  912. {
  913. //
  914. // Find where the server portion ends
  915. //
  916. WCHAR* pwcNextSlash = wcschr(wszPath+2, wszPath[0]);
  917. if(pwcNextSlash == NULL)
  918. return WBEM_E_INVALID_OBJECT_PATH;
  919. //
  920. // Find where the namespace portion ends
  921. //
  922. WCHAR* pwcColon = wcschr(pwcNextSlash, L':');
  923. if(pwcColon == NULL)
  924. return WBEM_E_INVALID_OBJECT_PATH;
  925. if(pwszNamespace)
  926. {
  927. DWORD dwLen = pwcColon - pwcNextSlash;
  928. *pwszNamespace = (WCHAR*)TempAlloc(dwLen * sizeof(WCHAR));
  929. if(*pwszNamespace == NULL)
  930. return WBEM_E_OUT_OF_MEMORY;
  931. *pwcColon = 0;
  932. wcscpy(*pwszNamespace, pwcNextSlash+1);
  933. }
  934. //
  935. // Advance wszPath to beyond the namespace portion
  936. //
  937. wszPath = pwcColon+1;
  938. }
  939. else if(pwszNamespace)
  940. {
  941. *pwszNamespace = NULL;
  942. }
  943. // Get the first key
  944. WCHAR* pwcFirstEq = wcschr(wszPath, L'=');
  945. if(pwcFirstEq == NULL)
  946. {
  947. //
  948. // It's a class!
  949. //
  950. *pbIsClass = true;
  951. // path to the "class" to distinguish from its instances
  952. wszKey[0] = 1;
  953. wszKey[1] = 0;
  954. *pwszClass = (WCHAR*)TempAlloc((wcslen(wszPath)+1) * sizeof(WCHAR));
  955. if(*pwszClass == NULL)
  956. {
  957. if(pwszNamespace)
  958. TempFree(*pwszNamespace);
  959. return WBEM_E_OUT_OF_MEMORY;
  960. }
  961. wcscpy(*pwszClass, wszPath);
  962. return S_OK;
  963. }
  964. WCHAR* pwcFirstDot = wcschr(wszPath, L'.');
  965. if(pwcFirstDot == NULL || pwcFirstDot > pwcFirstEq)
  966. {
  967. // No name on the first key
  968. *pwcFirstEq = 0;
  969. *pwszClass = (WCHAR*)TempAlloc((wcslen(wszPath)+1) * sizeof(WCHAR));
  970. if(*pwszClass == NULL)
  971. {
  972. if(pwszNamespace)
  973. TempFree(*pwszNamespace);
  974. return WBEM_E_OUT_OF_MEMORY;
  975. }
  976. wcscpy(*pwszClass, wszPath);
  977. WCHAR* pwcThisKey = NULL;
  978. WCHAR* pwcEnd = NULL;
  979. hres = ParseKey(pwcFirstEq+1, &pwcThisKey, &pwcEnd);
  980. if(FAILED(hres))
  981. {
  982. TempFree(*pwszClass);
  983. if(pwszNamespace)
  984. TempFree(*pwszNamespace);
  985. return hres;
  986. }
  987. if(*pwcEnd != NULL)
  988. {
  989. TempFree(*pwszClass);
  990. if(pwszNamespace)
  991. TempFree(*pwszNamespace);
  992. return WBEM_E_INVALID_OBJECT_PATH;
  993. }
  994. wcscpy(wszKey, pwcThisKey);
  995. return S_OK;
  996. }
  997. //
  998. // Normal case
  999. //
  1000. //
  1001. // Get all the key values
  1002. //
  1003. struct CKeyStruct
  1004. {
  1005. WCHAR* m_pwcValue;
  1006. WCHAR* m_pwcName;
  1007. } * aKeys = (CKeyStruct*)TempAlloc(sizeof(CKeyStruct[256]));
  1008. if (0==aKeys)
  1009. {
  1010. if(pwszNamespace)
  1011. TempFree(*pwszNamespace);
  1012. return WBEM_E_OUT_OF_MEMORY;
  1013. }
  1014. CTempFreeMe release_aKeys(aKeys);
  1015. DWORD dwNumKeys = 0;
  1016. *pwcFirstDot = NULL;
  1017. *pwszClass = (WCHAR*)TempAlloc((wcslen(wszPath)+1) * sizeof(WCHAR));
  1018. if(*pwszClass == NULL)
  1019. {
  1020. if(pwszNamespace)
  1021. TempFree(*pwszNamespace);
  1022. return WBEM_E_OUT_OF_MEMORY;
  1023. }
  1024. wcscpy(*pwszClass, wszPath);
  1025. WCHAR* pwcNextKey = pwcFirstDot+1;
  1026. do
  1027. {
  1028. pwcFirstEq = wcschr(pwcNextKey, L'=');
  1029. if(pwcFirstEq == NULL)
  1030. {
  1031. TempFree(*pwszClass);
  1032. if(pwszNamespace)
  1033. TempFree(*pwszNamespace);
  1034. return WBEM_E_INVALID_OBJECT_PATH;
  1035. }
  1036. *pwcFirstEq = 0;
  1037. aKeys[dwNumKeys].m_pwcName = pwcNextKey;
  1038. hres = ParseKey(pwcFirstEq+1, &(aKeys[dwNumKeys].m_pwcValue),
  1039. &pwcNextKey);
  1040. if(FAILED(hres))
  1041. {
  1042. TempFree(*pwszClass);
  1043. if(pwszNamespace)
  1044. TempFree(*pwszNamespace);
  1045. return hres;
  1046. }
  1047. dwNumKeys++;
  1048. }
  1049. while(*pwcNextKey);
  1050. if(*pwcNextKey != 0)
  1051. {
  1052. TempFree(*pwszClass);
  1053. if(pwszNamespace)
  1054. TempFree(*pwszNamespace);
  1055. return WBEM_E_INVALID_OBJECT_PATH;
  1056. }
  1057. //
  1058. // We have the array of keys --- sort it
  1059. //
  1060. DWORD dwCurrentIndex = 0;
  1061. while(dwCurrentIndex < dwNumKeys-1)
  1062. {
  1063. if(wbem_wcsicmp(aKeys[dwCurrentIndex].m_pwcName,
  1064. aKeys[dwCurrentIndex+1].m_pwcName) > 0)
  1065. {
  1066. CKeyStruct Temp = aKeys[dwCurrentIndex];
  1067. aKeys[dwCurrentIndex] = aKeys[dwCurrentIndex+1];
  1068. aKeys[dwCurrentIndex+1] = Temp;
  1069. if(dwCurrentIndex)
  1070. dwCurrentIndex--;
  1071. else
  1072. dwCurrentIndex++;
  1073. }
  1074. else
  1075. dwCurrentIndex++;
  1076. }
  1077. //
  1078. // Now generate the result
  1079. //
  1080. WCHAR* pwcKeyEnd = wszKey;
  1081. for(DWORD i = 0; i < dwNumKeys; i++)
  1082. {
  1083. wcscpy(pwcKeyEnd, aKeys[i].m_pwcValue);
  1084. pwcKeyEnd += wcslen(aKeys[i].m_pwcValue);
  1085. if(i < dwNumKeys-1)
  1086. *(pwcKeyEnd++) = -1;
  1087. }
  1088. *pwcKeyEnd = 0;
  1089. return S_OK;
  1090. }
  1091. CHR CNamespaceHandle::ParseKey(LPWSTR wszKeyStart, LPWSTR* pwcRealStart,
  1092. LPWSTR* pwcNextKey)
  1093. {
  1094. if(wszKeyStart[0] == L'"' || wszKeyStart[0] == L'\'')
  1095. {
  1096. WCHAR wcStart = wszKeyStart[0];
  1097. WCHAR* pwcRead = wszKeyStart+1;
  1098. WCHAR* pwcWrite = wszKeyStart+1;
  1099. while(*pwcRead && *pwcRead != wcStart)
  1100. {
  1101. if((*pwcRead == '\\') && (*(pwcRead+1) != 'x') && (*(pwcRead+1) != 'X'))
  1102. pwcRead++;
  1103. *(pwcWrite++) = *(pwcRead++);
  1104. }
  1105. if(*pwcRead == 0)
  1106. return WBEM_E_INVALID_OBJECT_PATH;
  1107. *pwcWrite = 0;
  1108. if(pwcRealStart)
  1109. *pwcRealStart = wszKeyStart+1;
  1110. //
  1111. // Check separator
  1112. //
  1113. if(pwcRead[1] && pwcRead[1] != L',')
  1114. return WBEM_E_INVALID_OBJECT_PATH;
  1115. if(pwcNextKey)
  1116. {
  1117. //
  1118. // If there is a separator, skip it. Don't skip end of string!
  1119. //
  1120. if(pwcRead[1])
  1121. *pwcNextKey = pwcRead+2;
  1122. else
  1123. *pwcNextKey = pwcRead+1;
  1124. }
  1125. }
  1126. else
  1127. {
  1128. if(pwcRealStart)
  1129. *pwcRealStart = wszKeyStart;
  1130. WCHAR* pwcComma = wcschr(wszKeyStart, L',');
  1131. if(pwcComma == NULL)
  1132. {
  1133. if(pwcNextKey)
  1134. *pwcNextKey = wszKeyStart + wcslen(wszKeyStart);
  1135. }
  1136. else
  1137. {
  1138. *pwcComma = 0;
  1139. if(pwcNextKey)
  1140. *pwcNextKey = pwcComma+1;
  1141. }
  1142. }
  1143. return S_OK;
  1144. }
  1145. CHR CNamespaceHandle::GetObjectDirect(
  1146. IWbemPath *pPath,
  1147. DWORD dwFlags,
  1148. REFIID riid,
  1149. LPVOID *pObj
  1150. )
  1151. {
  1152. HRESULT hres;
  1153. DWORD dwLen = 0;
  1154. hres = pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, NULL);
  1155. LPWSTR wszPath = (WCHAR*)TempAlloc(dwLen*sizeof(WCHAR));
  1156. if (wszPath == NULL)
  1157. return WBEM_E_OUT_OF_MEMORY;
  1158. CTempFreeMe vdm(wszPath, dwLen * sizeof(WCHAR));
  1159. hres = pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, wszPath);
  1160. if(FAILED(hres))
  1161. return hres;
  1162. return GetObjectByPath(wszPath, dwFlags, riid, pObj);
  1163. }
  1164. CHR CNamespaceHandle::GetObjectByPath(
  1165. LPWSTR wszPath,
  1166. DWORD dwFlags,
  1167. REFIID riid,
  1168. LPVOID *pObj
  1169. )
  1170. {
  1171. HRESULT hres;
  1172. //
  1173. // Get the key from path
  1174. //
  1175. DWORD dwLen = wcslen(wszPath)*sizeof(WCHAR)+2;
  1176. LPWSTR wszKey = (WCHAR*)TempAlloc(dwLen);
  1177. if(wszKey == NULL)
  1178. return WBEM_E_OUT_OF_MEMORY;
  1179. CTempFreeMe tfm(wszKey, dwLen);
  1180. bool bIsClass;
  1181. LPWSTR wszClassName = NULL;
  1182. hres = ComputeKeyFromPath(wszPath, wszKey, &wszClassName, &bIsClass);
  1183. if(FAILED(hres))
  1184. return hres;
  1185. CTempFreeMe tfm1(wszClassName, (wcslen(wszClassName)+1) * sizeof(WCHAR*));
  1186. if(bIsClass)
  1187. {
  1188. return GetClassDirect(wszClassName, riid, pObj, true, NULL, NULL, NULL);
  1189. }
  1190. else
  1191. {
  1192. return GetInstanceByKey(wszClassName, wszKey, riid, pObj);
  1193. }
  1194. }
  1195. CHR CNamespaceHandle::GetInstanceByKey(LPCWSTR wszClassName,
  1196. LPCWSTR wszKey,
  1197. REFIID riid, void** ppObj)
  1198. {
  1199. HRESULT hres;
  1200. //
  1201. // Get the class definition
  1202. //
  1203. _IWmiObject* pClass = NULL;
  1204. hres = GetClassDirect(wszClassName, IID__IWmiObject, (void**)&pClass,
  1205. false, NULL, NULL, NULL);
  1206. if(FAILED(hres))
  1207. return hres;
  1208. CReleaseMe rm1(pClass);
  1209. //
  1210. // Construct directory path
  1211. //
  1212. CFileName wszFilePath;
  1213. if (wszFilePath == NULL)
  1214. return WBEM_E_OUT_OF_MEMORY;
  1215. hres = ConstructKeyRootDirFromClass(wszFilePath, wszClassName);
  1216. if(FAILED(hres))
  1217. return hres;
  1218. //
  1219. // Construct the file path
  1220. //
  1221. int nLen = wcslen(wszFilePath);
  1222. wszFilePath[nLen] = L'\\';
  1223. hres = ConstructInstanceDefName(wszFilePath+nLen+1, wszKey);
  1224. if(FAILED(hres))
  1225. return hres;
  1226. //
  1227. // Get the object from that file
  1228. //
  1229. _IWmiObject* pInst;
  1230. hres = FileToInstance(NULL, wszFilePath, NULL, 0, &pInst);
  1231. if(FAILED(hres))
  1232. return hres;
  1233. CReleaseMe rm2(pInst);
  1234. //
  1235. // Return
  1236. //
  1237. return pInst->QueryInterface(riid, (void**)ppObj);
  1238. }
  1239. CHR CNamespaceHandle::GetClassByHash(LPCWSTR wszHash, bool bClone,
  1240. _IWmiObject** ppClass,
  1241. __int64* pnTime,
  1242. bool* pbRead,
  1243. bool *pbSystemClass)
  1244. {
  1245. HRESULT hres;
  1246. //
  1247. // Check the cache first
  1248. //
  1249. *ppClass = m_pClassCache->GetClassDefByHash(wszHash, bClone, pnTime, pbRead, pbSystemClass);
  1250. if(*ppClass)
  1251. return S_OK;
  1252. //
  1253. // Not found --- construct the file name and read it
  1254. //
  1255. if(pbRead)
  1256. *pbRead = true;
  1257. CFileName wszFileName;
  1258. if (wszFileName == NULL)
  1259. return WBEM_E_OUT_OF_MEMORY;
  1260. hres = ConstructClassDefFileNameFromHash(wszHash, wszFileName);
  1261. if(FAILED(hres))
  1262. return hres;
  1263. CFileName wszFilePath;
  1264. if (wszFilePath == NULL)
  1265. return WBEM_E_OUT_OF_MEMORY;
  1266. swprintf(wszFilePath, L"%s\\%s", m_wszClassRootDir, wszFileName);
  1267. hres = FileToClass(wszFilePath, ppClass, bClone, pnTime, pbSystemClass);
  1268. if(FAILED(hres))
  1269. return hres;
  1270. return S_OK;
  1271. }
  1272. CHR CNamespaceHandle::GetClassDirect(LPCWSTR wszClassName,
  1273. REFIID riid, void** ppObj, bool bClone,
  1274. __int64* pnTime, bool* pbRead,
  1275. bool *pbSystemClass)
  1276. {
  1277. HRESULT hres;
  1278. if(wszClassName == NULL || wcslen(wszClassName) == 0)
  1279. {
  1280. if(m_pNullClass == NULL)
  1281. {
  1282. hres = CoCreateInstance(CLSID_WbemClassObject, NULL,
  1283. CLSCTX_INPROC_SERVER,
  1284. IID__IWmiObject, (void **)&m_pNullClass);
  1285. if (FAILED(hres))
  1286. return hres;
  1287. }
  1288. IWbemClassObject* pRawObj;
  1289. hres = m_pNullClass->Clone(&pRawObj);
  1290. if (FAILED(hres))
  1291. return hres;
  1292. CReleaseMe rm(pRawObj);
  1293. if(pnTime)
  1294. *pnTime = 0;
  1295. if(pbRead)
  1296. *pbRead = false;
  1297. return pRawObj->QueryInterface(riid, ppObj);
  1298. }
  1299. _IWmiObject* pClass;
  1300. //
  1301. // Check the cache first
  1302. //
  1303. pClass = m_pClassCache->GetClassDef(wszClassName, bClone, pnTime, pbRead);
  1304. if(pClass)
  1305. {
  1306. CReleaseMe rm1(pClass);
  1307. return pClass->QueryInterface(riid, ppObj);
  1308. }
  1309. if(pbRead)
  1310. *pbRead = true;
  1311. //
  1312. // Construct the path for the file
  1313. //
  1314. CFileName wszFileName;
  1315. if (wszFileName == NULL)
  1316. return WBEM_E_OUT_OF_MEMORY;
  1317. hres = ConstructClassDefFileName(wszClassName, wszFileName);
  1318. if(FAILED(hres))
  1319. return hres;
  1320. CFileName wszFilePath;
  1321. if (wszFilePath == NULL)
  1322. return WBEM_E_OUT_OF_MEMORY;
  1323. swprintf(wszFilePath, L"%s\\%s", m_wszClassRootDir, wszFileName);
  1324. //
  1325. // Read it from the file
  1326. //
  1327. hres = FileToClass(wszFilePath, &pClass, bClone, pnTime, pbSystemClass);
  1328. if(FAILED(hres))
  1329. return hres;
  1330. CReleaseMe rm1(pClass);
  1331. return pClass->QueryInterface(riid, ppObj);
  1332. }
  1333. CHR CNamespaceHandle::FileToInstance(_IWmiObject* pClass,
  1334. LPCWSTR wszFileName,
  1335. BYTE *pRetrievedBlob,
  1336. DWORD dwSize,
  1337. _IWmiObject** ppInstance,
  1338. bool bMustBeThere)
  1339. {
  1340. HRESULT hres;
  1341. //
  1342. // Read the data from the file
  1343. //
  1344. BYTE* pBlob = NULL;
  1345. if (pRetrievedBlob == NULL)
  1346. {
  1347. long lRes = g_Glob.GetFileCache()->ReadObject(wszFileName, &dwSize, &pBlob,
  1348. bMustBeThere);
  1349. if(lRes != ERROR_SUCCESS)
  1350. {
  1351. if(lRes == ERROR_FILE_NOT_FOUND || lRes == ERROR_PATH_NOT_FOUND)
  1352. return WBEM_E_NOT_FOUND;
  1353. else
  1354. return WBEM_E_FAILED;
  1355. }
  1356. pRetrievedBlob = pBlob;
  1357. }
  1358. CTempFreeMe tfm1(pBlob, dwSize);
  1359. _ASSERT(dwSize > sizeof(__int64), L"Instance blob too short");
  1360. if(dwSize <= sizeof(__int64))
  1361. return WBEM_E_OUT_OF_MEMORY;
  1362. //
  1363. // Extract the class hash
  1364. //
  1365. WCHAR wszClassHash[MAX_HASH_LEN+1];
  1366. DWORD dwClassHashLen = MAX_HASH_LEN*sizeof(WCHAR);
  1367. memcpy(wszClassHash, pRetrievedBlob, MAX_HASH_LEN*sizeof(WCHAR));
  1368. wszClassHash[MAX_HASH_LEN] = 0;
  1369. __int64 nInstanceTime;
  1370. memcpy(&nInstanceTime, pRetrievedBlob + dwClassHashLen, sizeof(__int64));
  1371. __int64 nOldClassTime;
  1372. memcpy(&nOldClassTime, pRetrievedBlob + dwClassHashLen + sizeof(__int64),
  1373. sizeof(__int64));
  1374. BYTE* pInstancePart = pRetrievedBlob + dwClassHashLen + sizeof(__int64)*2;
  1375. DWORD dwInstancePartSize = dwSize - dwClassHashLen - sizeof(__int64)*2;
  1376. //
  1377. // Get the class def
  1378. //
  1379. _IWmiObject* pRetrievedClass = NULL;
  1380. if (pClass == NULL)
  1381. {
  1382. __int64 nClassTime;
  1383. bool bRead;
  1384. bool bSystemClass = false;
  1385. hres = GetClassByHash(wszClassHash, false, &pRetrievedClass, &nClassTime, &bRead, &bSystemClass);
  1386. if(FAILED(hres))
  1387. return hres;
  1388. pClass = pRetrievedClass;
  1389. }
  1390. CReleaseMe rm1(pRetrievedClass);
  1391. #ifdef A51_CHECK_TIMESTAMPS
  1392. _ASSERT(nClassTime <= nInstanceTime, L"Instance is older than its class");
  1393. _ASSERT(nClassTime == nOldClassTime, L"Instance verified with the wrong "
  1394. L"class definition");
  1395. #endif
  1396. //
  1397. // Construct the instance
  1398. //
  1399. _IWmiObject* pInst = NULL;
  1400. hres = pClass->Merge(WMIOBJECT_MERGE_FLAG_INSTANCE,
  1401. dwInstancePartSize, pInstancePart, &pInst);
  1402. if(FAILED(hres))
  1403. return hres;
  1404. //
  1405. // Decorate it
  1406. //
  1407. pInst->SetDecoration(m_wszMachineName, m_wsNamespace);
  1408. A51TRACE(("Read instance from %S in namespace %S\n",
  1409. wszFileName, (LPCWSTR)m_wsNamespace));
  1410. *ppInstance = pInst;
  1411. return S_OK;
  1412. }
  1413. CHR CNamespaceHandle::FileToSystemClass(LPCWSTR wszFileName,
  1414. _IWmiObject** ppClass, bool bClone,
  1415. __int64* pnTime)
  1416. {
  1417. //
  1418. // Note: we must always clone the result of the system class retrieval,
  1419. // since it will be decorated by the caller
  1420. //
  1421. return GetClassByHash(wszFileName + (wcslen(wszFileName) - MAX_HASH_LEN),
  1422. true,
  1423. ppClass, pnTime, NULL, NULL);
  1424. }
  1425. CHR CNamespaceHandle::FileToClass(LPCWSTR wszFileName,
  1426. _IWmiObject** ppClass, bool bClone,
  1427. __int64* pnTime, bool *pbSystemClass)
  1428. {
  1429. HRESULT hres;
  1430. //
  1431. // Read the data from the file
  1432. //
  1433. __int64 nTime;
  1434. DWORD dwSize;
  1435. BYTE* pBlob;
  1436. VARIANT vClass;
  1437. long lRes = g_Glob.GetFileCache()->ReadObject(wszFileName, &dwSize, &pBlob);
  1438. if(lRes != ERROR_SUCCESS)
  1439. {
  1440. //We didn't find it here, so lets try and find it in the default namespace!
  1441. //If we are not in the __SYSTEMCLASS namespace then we need to call into that...
  1442. if((lRes == ERROR_FILE_NOT_FOUND || lRes == ERROR_PATH_NOT_FOUND) && g_pSystemClassNamespace && wcscmp(m_wsNamespace, A51_SYSTEMCLASS_NS) != 0)
  1443. {
  1444. hres = g_pSystemClassNamespace->FileToSystemClass(wszFileName, ppClass, bClone, &nTime);
  1445. if (FAILED(hres))
  1446. return hres;
  1447. if (pnTime)
  1448. *pnTime = nTime;
  1449. //need to cache this item in the local cache
  1450. hres = (*ppClass)->Get(L"__CLASS", 0, &vClass, NULL, NULL);
  1451. if(FAILED(hres) || V_VT(&vClass) != VT_BSTR)
  1452. return WBEM_E_INVALID_OBJECT;
  1453. CClearMe cm1(&vClass);
  1454. A51TRACE(("Read class %S from disk in namespace %S\n", V_BSTR(&vClass), m_wsNamespace));
  1455. (*ppClass)->SetDecoration(m_wszMachineName, m_wsNamespace);
  1456. m_pClassCache->AssertClass((*ppClass), V_BSTR(&vClass), bClone, nTime, true);
  1457. if (pbSystemClass)
  1458. *pbSystemClass = true;
  1459. return hres;
  1460. }
  1461. else if (lRes == ERROR_FILE_NOT_FOUND || lRes == ERROR_PATH_NOT_FOUND)
  1462. return WBEM_E_NOT_FOUND;
  1463. else
  1464. return WBEM_E_FAILED;
  1465. }
  1466. CTempFreeMe tfm1(pBlob, dwSize);
  1467. _ASSERT(dwSize > sizeof(__int64), L"Class blob too short");
  1468. if(dwSize <= sizeof(__int64))
  1469. return WBEM_E_OUT_OF_MEMORY;
  1470. //
  1471. // Read off the superclass name
  1472. //
  1473. DWORD dwSuperLen;
  1474. memcpy(&dwSuperLen, pBlob, sizeof(DWORD));
  1475. LPWSTR wszSuperClass = (WCHAR*)TempAlloc(dwSuperLen*sizeof(WCHAR)+2);
  1476. if (wszSuperClass == NULL)
  1477. return WBEM_E_OUT_OF_MEMORY;
  1478. CTempFreeMe vdm1(wszSuperClass, dwSuperLen*sizeof(WCHAR)+2);
  1479. wszSuperClass[dwSuperLen] = 0;
  1480. memcpy(wszSuperClass, pBlob+sizeof(DWORD), dwSuperLen*sizeof(WCHAR));
  1481. DWORD dwPrefixLen = sizeof(DWORD) + dwSuperLen*sizeof(WCHAR);
  1482. memcpy(&nTime, pBlob + dwPrefixLen, sizeof(__int64));
  1483. //
  1484. // Get the superclass
  1485. //
  1486. _IWmiObject* pSuperClass;
  1487. __int64 nSuperTime;
  1488. bool bRead;
  1489. hres = GetClassDirect(wszSuperClass, IID__IWmiObject, (void**)&pSuperClass,
  1490. false, &nSuperTime, &bRead, NULL);
  1491. if(FAILED(hres))
  1492. return WBEM_E_CRITICAL_ERROR;
  1493. CReleaseMe rm1(pSuperClass);
  1494. #ifdef A51_CHECK_TIMESTAMPS
  1495. _ASSERT(nSuperTime <= nTime, L"Parent class is older than child");
  1496. #endif
  1497. DWORD dwClassLen = dwSize - dwPrefixLen - sizeof(__int64);
  1498. _IWmiObject* pNewObj;
  1499. hres = pSuperClass->Merge(0, dwClassLen,
  1500. pBlob + dwPrefixLen + sizeof(__int64), &pNewObj);
  1501. if(FAILED(hres))
  1502. return hres;
  1503. //
  1504. // Decorate it
  1505. //
  1506. pNewObj->SetDecoration(m_wszMachineName, m_wsNamespace);
  1507. //
  1508. // Cache it!
  1509. //
  1510. hres = pNewObj->Get(L"__CLASS", 0, &vClass, NULL, NULL);
  1511. if(FAILED(hres) || V_VT(&vClass) != VT_BSTR)
  1512. return WBEM_E_INVALID_OBJECT;
  1513. CClearMe cm1(&vClass);
  1514. A51TRACE(("Read class %S from disk in namespace %S\n",
  1515. V_BSTR(&vClass), m_wsNamespace));
  1516. m_pClassCache->AssertClass(pNewObj, V_BSTR(&vClass), bClone, nTime, false);
  1517. *ppClass = pNewObj;
  1518. if(pnTime)
  1519. *pnTime = nTime;
  1520. if (pbSystemClass)
  1521. *pbSystemClass = false;
  1522. return S_OK;
  1523. }
  1524. CHR CNamespaceHandle::PutObject(
  1525. REFIID riid,
  1526. LPVOID pObj,
  1527. DWORD dwFlags,
  1528. DWORD dwRequestedHandleType,
  1529. IWmiDbHandle **ppResult,
  1530. CEventCollector &aEvents
  1531. )
  1532. {
  1533. HRESULT hres;
  1534. _IWmiObject* pObjEx = NULL;
  1535. ((IUnknown*)pObj)->QueryInterface(IID__IWmiObject, (void**)&pObjEx);
  1536. CReleaseMe rm1(pObjEx);
  1537. if(pObjEx->IsObjectInstance() == S_OK)
  1538. {
  1539. hres = PutInstance(pObjEx, dwFlags, aEvents);
  1540. }
  1541. else
  1542. {
  1543. hres = PutClass(pObjEx, dwFlags, aEvents);
  1544. }
  1545. if(FAILED(hres))
  1546. return hres;
  1547. if(ppResult)
  1548. {
  1549. //
  1550. // Got to get a handle
  1551. //
  1552. VARIANT v;
  1553. hres = pObjEx->Get(L"__RELPATH", 0, &v, NULL, NULL);
  1554. if(FAILED(hres) || V_VT(&v) != VT_BSTR)
  1555. return WBEM_E_INVALID_OBJECT;
  1556. hres = GetObjectHandleByPath(V_BSTR(&v), 0, WMIDB_HANDLE_TYPE_COOKIE,
  1557. ppResult);
  1558. if(FAILED(hres))
  1559. return hres;
  1560. }
  1561. return S_OK;
  1562. }
  1563. CHR CNamespaceHandle::PutInstance(_IWmiObject* pInst, DWORD dwFlags,
  1564. CEventCollector &aEvents)
  1565. {
  1566. HRESULT hres;
  1567. bool bDisableEvents = ((dwFlags & WMIDB_DISABLE_EVENTS)?true:false);
  1568. //
  1569. // Get the class name
  1570. //
  1571. VARIANT vClass;
  1572. hres = pInst->Get(L"__CLASS", 0, &vClass, NULL, NULL);
  1573. if(FAILED(hres) || V_VT(&vClass) != VT_BSTR)
  1574. return WBEM_E_INVALID_OBJECT;
  1575. CClearMe cm1(&vClass);
  1576. LPCWSTR wszClassName = V_BSTR(&vClass);
  1577. //
  1578. // Get the class so we can compare to make sure it is the same class used to
  1579. // create the instance
  1580. //
  1581. _IWmiObject* pClass = NULL;
  1582. __int64 nClassTime;
  1583. hres = GetClassDirect(wszClassName, IID__IWmiObject, (void**)&pClass,
  1584. false, &nClassTime, NULL, NULL);
  1585. if(FAILED(hres))
  1586. return hres;
  1587. CReleaseMe rm2(pClass);
  1588. if(wszClassName[0] != L'_')
  1589. {
  1590. hres = pInst->IsParentClass(0, pClass);
  1591. if(FAILED(hres))
  1592. return hres;
  1593. if(hres == WBEM_S_FALSE)
  1594. return WBEM_E_INVALID_CLASS;
  1595. }
  1596. //
  1597. // Get the path
  1598. //
  1599. VARIANT var;
  1600. VariantInit(&var);
  1601. hres = pInst->Get(L"__relpath", 0, &var, 0, 0);
  1602. if (FAILED(hres))
  1603. return hres;
  1604. CClearMe cm2(&var);
  1605. DWORD dwLen = (wcslen(V_BSTR(&var)) + 1) * sizeof(WCHAR);
  1606. LPWSTR strKey = (WCHAR*)TempAlloc(dwLen);
  1607. if(strKey == NULL)
  1608. return WBEM_E_OUT_OF_MEMORY;
  1609. CTempFreeMe tfm(strKey, dwLen);
  1610. bool bIsClass;
  1611. LPWSTR __wszClassName = NULL;
  1612. hres = ComputeKeyFromPath(V_BSTR(&var), strKey, &__wszClassName, &bIsClass);
  1613. if(FAILED(hres))
  1614. return hres;
  1615. CTempFreeMe tfm1(__wszClassName);
  1616. A51TRACE(("Putting instance %S of class %S\n", strKey, wszClassName));
  1617. //
  1618. // Get the old copy
  1619. //
  1620. _IWmiObject* pOldInst = NULL;
  1621. hres = GetInstanceByKey(wszClassName, strKey, IID__IWmiObject,
  1622. (void**)&pOldInst);
  1623. if(FAILED(hres) && hres != WBEM_E_NOT_FOUND)
  1624. return hres;
  1625. CReleaseMe rm1(pOldInst);
  1626. if ((dwFlags & WBEM_FLAG_CREATE_ONLY) && (hres != WBEM_E_NOT_FOUND))
  1627. return WBEM_E_ALREADY_EXISTS;
  1628. else if ((dwFlags & WBEM_FLAG_UPDATE_ONLY) && (hres != WBEM_S_NO_ERROR))
  1629. return WBEM_E_NOT_FOUND;
  1630. if(pOldInst)
  1631. {
  1632. //
  1633. // Check that this guy is of the same class as the new one
  1634. //
  1635. //
  1636. // Get the class name
  1637. //
  1638. VARIANT vClass2;
  1639. hres = pOldInst->Get(L"__CLASS", 0, &vClass2, NULL, NULL);
  1640. if(FAILED(hres))
  1641. return hres;
  1642. if(V_VT(&vClass2) != VT_BSTR)
  1643. return WBEM_E_INVALID_OBJECT;
  1644. CClearMe cm3(&vClass2);
  1645. if(wbem_wcsicmp(V_BSTR(&vClass2), wszClassName))
  1646. return WBEM_E_INVALID_CLASS;
  1647. }
  1648. //
  1649. // Construct the hash for the file
  1650. //
  1651. CFileName wszInstanceHash;
  1652. if (wszInstanceHash == NULL)
  1653. return WBEM_E_OUT_OF_MEMORY;
  1654. if(!Hash(strKey, wszInstanceHash))
  1655. return WBEM_E_OUT_OF_MEMORY;
  1656. //
  1657. // Construct the path to the instance file in key root
  1658. //
  1659. CFileName wszInstanceFilePath;
  1660. if (wszInstanceFilePath == NULL)
  1661. return WBEM_E_OUT_OF_MEMORY;
  1662. hres = ConstructKeyRootDirFromClass(wszInstanceFilePath, wszClassName);
  1663. if(FAILED(hres))
  1664. return hres;
  1665. wcscat(wszInstanceFilePath, L"\\" A51_INSTDEF_FILE_PREFIX);
  1666. wcscat(wszInstanceFilePath, wszInstanceHash);
  1667. //
  1668. // Construct the path to the link file under the class
  1669. //
  1670. CFileName wszInstanceLinkPath;
  1671. if (wszInstanceLinkPath == NULL)
  1672. return WBEM_E_OUT_OF_MEMORY;
  1673. hres = ConstructLinkDirFromClass(wszInstanceLinkPath, wszClassName);
  1674. if(FAILED(hres))
  1675. return hres;
  1676. wcscat(wszInstanceLinkPath, L"\\" A51_INSTLINK_FILE_PREFIX);
  1677. wcscat(wszInstanceLinkPath, wszInstanceHash);
  1678. //
  1679. // Clean up what was there, if anything
  1680. //
  1681. if(pOldInst)
  1682. {
  1683. //
  1684. // Just delete it, but be careful not to delete the scope!
  1685. //
  1686. hres = DeleteInstanceSelf(wszInstanceFilePath, pOldInst, false);
  1687. if(FAILED(hres) && hres != WBEM_E_NOT_FOUND)
  1688. return hres;
  1689. }
  1690. //
  1691. // Create the actual instance def under key root
  1692. //
  1693. hres = InstanceToFile(pInst, wszClassName, wszInstanceFilePath, wszInstanceLinkPath, nClassTime);
  1694. if(FAILED(hres))
  1695. return hres;
  1696. //
  1697. // Write the references
  1698. //
  1699. hres = WriteInstanceReferences(pInst, wszClassName, wszInstanceFilePath);
  1700. if(FAILED(hres))
  1701. return hres;
  1702. if(!bDisableEvents)
  1703. {
  1704. //
  1705. // Fire Event
  1706. //
  1707. if(pInst->InheritsFrom(L"__Namespace") == S_OK)
  1708. {
  1709. //
  1710. // Get the namespace name
  1711. //
  1712. VARIANT vClass2;
  1713. VariantInit(&vClass2);
  1714. CClearMe cm3(&vClass2);
  1715. hres = pInst->Get(L"Name", 0, &vClass2, NULL, NULL);
  1716. if(FAILED(hres) || V_VT(&vClass2) != VT_BSTR)
  1717. return WBEM_E_INVALID_OBJECT;
  1718. if(pOldInst)
  1719. {
  1720. hres = FireEvent(aEvents, WBEM_EVENTTYPE_NamespaceModification,
  1721. V_BSTR(&vClass2), pInst, pOldInst);
  1722. }
  1723. else
  1724. {
  1725. hres = FireEvent(aEvents, WBEM_EVENTTYPE_NamespaceCreation,
  1726. V_BSTR(&vClass2), pInst);
  1727. }
  1728. }
  1729. else
  1730. {
  1731. if(pOldInst)
  1732. {
  1733. hres = FireEvent(aEvents, WBEM_EVENTTYPE_InstanceModification,
  1734. wszClassName, pInst, pOldInst);
  1735. }
  1736. else
  1737. {
  1738. hres = FireEvent(aEvents, WBEM_EVENTTYPE_InstanceCreation,
  1739. wszClassName, pInst);
  1740. }
  1741. }
  1742. }
  1743. A51TRACE(("PutInstance for %S of class %S succeeded\n",
  1744. strKey, wszClassName));
  1745. return S_OK;
  1746. }
  1747. CHR CNamespaceHandle::GetKeyRoot(LPCWSTR wszClass,
  1748. TEMPFREE_ME LPWSTR* pwszKeyRootClass)
  1749. {
  1750. HRESULT hres;
  1751. //
  1752. // Look in the cache first
  1753. //
  1754. hres = m_pClassCache->GetKeyRoot(wszClass, pwszKeyRootClass);
  1755. if(hres == S_OK)
  1756. return S_OK;
  1757. else if(hres == WBEM_E_CANNOT_BE_ABSTRACT)
  1758. return WBEM_E_CANNOT_BE_ABSTRACT;
  1759. //
  1760. // Walk up the tree getting classes until you hit an unkeyed one
  1761. //
  1762. WString wsThisName = wszClass;
  1763. WString wsPreviousName;
  1764. while(1)
  1765. {
  1766. _IWmiObject* pClass = NULL;
  1767. hres = GetClassDirect(wsThisName, IID__IWmiObject, (void**)&pClass,
  1768. false, NULL, NULL, NULL);
  1769. if(FAILED(hres))
  1770. return hres;
  1771. CReleaseMe rm1(pClass);
  1772. //
  1773. // Check if this class is keyed
  1774. //
  1775. unsigned __int64 i64Flags = 0;
  1776. hres = pClass->QueryObjectFlags(0, WMIOBJECT_GETOBJECT_LOFLAG_KEYED,
  1777. &i64Flags);
  1778. if(FAILED(hres))
  1779. return hres;
  1780. if(i64Flags == 0)
  1781. {
  1782. //
  1783. // It is not keyed --- the previous class wins!
  1784. //
  1785. if(wsPreviousName.Length() == 0)
  1786. return WBEM_E_CANNOT_BE_ABSTRACT;
  1787. DWORD dwLen = (wsPreviousName.Length()+1)*sizeof(WCHAR);
  1788. *pwszKeyRootClass = (WCHAR*)TempAlloc(dwLen);
  1789. if (*pwszKeyRootClass == NULL)
  1790. return WBEM_E_OUT_OF_MEMORY;
  1791. wcscpy(*pwszKeyRootClass, (LPCWSTR)wsPreviousName);
  1792. return S_OK;
  1793. }
  1794. //
  1795. // It is keyed --- get the parent and continue;
  1796. //
  1797. VARIANT vParent;
  1798. VariantInit(&vParent);
  1799. CClearMe cm(&vParent);
  1800. hres = pClass->Get(L"__SUPERCLASS", 0, &vParent, NULL, NULL);
  1801. if(FAILED(hres))
  1802. return hres;
  1803. if(V_VT(&vParent) != VT_BSTR)
  1804. {
  1805. //
  1806. // We've reached the top --- return this class
  1807. //
  1808. DWORD dwLen = (wsThisName.Length()+1)*sizeof(WCHAR);
  1809. *pwszKeyRootClass = (WCHAR*)TempAlloc(dwLen);
  1810. if (*pwszKeyRootClass == NULL)
  1811. return WBEM_E_OUT_OF_MEMORY;
  1812. wcscpy(*pwszKeyRootClass, (LPCWSTR)wsThisName);
  1813. return S_OK;
  1814. }
  1815. wsPreviousName = wsThisName;
  1816. wsThisName = V_BSTR(&vParent);
  1817. }
  1818. // Never here
  1819. DebugBreak();
  1820. return WBEM_E_CRITICAL_ERROR;
  1821. }
  1822. CHR CNamespaceHandle::GetKeyRootByHash(LPCWSTR wszClassHash,
  1823. TEMPFREE_ME LPWSTR* pwszKeyRootClass)
  1824. {
  1825. //
  1826. // Look in the cache first
  1827. //
  1828. HRESULT hres = m_pClassCache->GetKeyRootByKey(wszClassHash,
  1829. pwszKeyRootClass);
  1830. if(hres == S_OK)
  1831. return S_OK;
  1832. else if(hres == WBEM_E_CANNOT_BE_ABSTRACT)
  1833. return WBEM_E_CANNOT_BE_ABSTRACT;
  1834. //
  1835. // NOTE: this could be done more efficiently, but it happens once in a
  1836. // lifetime, so it's not worth the complexity.
  1837. //
  1838. //
  1839. // Get Class definition
  1840. //
  1841. _IWmiObject* pClass = NULL;
  1842. hres = GetClassByHash(wszClassHash, false, &pClass, NULL, NULL, NULL);
  1843. if(FAILED(hres))
  1844. return hres;
  1845. CReleaseMe rm1(pClass);
  1846. //
  1847. // Get the class name
  1848. //
  1849. VARIANT vClass;
  1850. hres = pClass->Get(L"__CLASS", 0, &vClass, NULL, NULL);
  1851. if(FAILED(hres) || (V_VT(&vClass) != VT_BSTR) ||
  1852. !V_BSTR(&vClass) || !wcslen(V_BSTR(&vClass)))
  1853. {
  1854. return WBEM_E_INVALID_OBJECT;
  1855. }
  1856. CClearMe cm1(&vClass);
  1857. LPCWSTR wszClassName = V_BSTR(&vClass);
  1858. //
  1859. // Now get it by name
  1860. //
  1861. return GetKeyRoot(wszClassName, pwszKeyRootClass);
  1862. }
  1863. CHR CNamespaceHandle::ConstructKeyRootDirFromClass(LPWSTR wszDir,
  1864. LPCWSTR wszClassName)
  1865. {
  1866. HRESULT hres;
  1867. //
  1868. // NULL class stands for "meta-class"
  1869. //
  1870. if(wszClassName == NULL)
  1871. return ConstructKeyRootDirFromKeyRoot(wszDir, L"");
  1872. //
  1873. // Figure out the key root for the class
  1874. //
  1875. LPWSTR wszKeyRootClass = NULL;
  1876. hres = GetKeyRoot(wszClassName, &wszKeyRootClass);
  1877. if(FAILED(hres))
  1878. return hres;
  1879. if(wszKeyRootClass == NULL)
  1880. {
  1881. // Abstract class --- bad error
  1882. return WBEM_E_INVALID_CLASS;
  1883. }
  1884. CTempFreeMe tfm(wszKeyRootClass, (wcslen(wszKeyRootClass)+1)*sizeof(WCHAR));
  1885. return ConstructKeyRootDirFromKeyRoot(wszDir, wszKeyRootClass);
  1886. }
  1887. CHR CNamespaceHandle::ConstructKeyRootDirFromClassHash(LPWSTR wszDir,
  1888. LPCWSTR wszClassHash)
  1889. {
  1890. HRESULT hres;
  1891. //
  1892. // Figure out the key root for the class
  1893. //
  1894. LPWSTR wszKeyRootClass = NULL;
  1895. hres = GetKeyRootByHash(wszClassHash, &wszKeyRootClass);
  1896. if(FAILED(hres))
  1897. return hres;
  1898. if(wszKeyRootClass == NULL)
  1899. {
  1900. // Abstract class --- bad error
  1901. return WBEM_E_INVALID_CLASS;
  1902. }
  1903. CTempFreeMe tfm(wszKeyRootClass, (wcslen(wszKeyRootClass)+1)*sizeof(WCHAR));
  1904. return ConstructKeyRootDirFromKeyRoot(wszDir, wszKeyRootClass);
  1905. }
  1906. CHR CNamespaceHandle::ConstructKeyRootDirFromKeyRoot(LPWSTR wszDir,
  1907. LPCWSTR wszKeyRootClass)
  1908. {
  1909. wcscpy(wszDir, m_wszInstanceRootDir);
  1910. wszDir[m_lInstanceRootDirLen] = L'\\';
  1911. wcscpy(wszDir+m_lInstanceRootDirLen+1, A51_KEYROOTINST_DIR_PREFIX);
  1912. if(!Hash(wszKeyRootClass,
  1913. wszDir+m_lInstanceRootDirLen+wcslen(A51_KEYROOTINST_DIR_PREFIX)+1))
  1914. {
  1915. return WBEM_E_OUT_OF_MEMORY;
  1916. }
  1917. return S_OK;
  1918. }
  1919. CHR CNamespaceHandle::ConstructLinkDirFromClass(LPWSTR wszDir,
  1920. LPCWSTR wszClassName)
  1921. {
  1922. wcscpy(wszDir, m_wszInstanceRootDir);
  1923. wszDir[m_lInstanceRootDirLen] = L'\\';
  1924. wcscpy(wszDir+m_lInstanceRootDirLen+1, A51_CLASSINST_DIR_PREFIX);
  1925. if(!Hash(wszClassName,
  1926. wszDir+m_lInstanceRootDirLen+wcslen(A51_CLASSINST_DIR_PREFIX)+1))
  1927. {
  1928. return WBEM_E_OUT_OF_MEMORY;
  1929. }
  1930. return S_OK;
  1931. }
  1932. CHR CNamespaceHandle::ConstructLinkDirFromClassHash(LPWSTR wszDir,
  1933. LPCWSTR wszClassHash)
  1934. {
  1935. wcscpy(wszDir, m_wszInstanceRootDir);
  1936. wszDir[m_lInstanceRootDirLen] = L'\\';
  1937. wcscpy(wszDir+m_lInstanceRootDirLen+1, A51_CLASSINST_DIR_PREFIX);
  1938. wcscat(wszDir, wszClassHash);
  1939. return S_OK;
  1940. }
  1941. CHR CNamespaceHandle::WriteInstanceReferences(_IWmiObject* pInst,
  1942. LPCWSTR wszClassName,
  1943. LPCWSTR wszFilePath)
  1944. {
  1945. HRESULT hres;
  1946. hres = pInst->BeginEnumeration(WBEM_FLAG_REFS_ONLY);
  1947. if(FAILED(hres))
  1948. return hres;
  1949. VARIANT v;
  1950. BSTR strName;
  1951. while((hres = pInst->Next(0, &strName, &v, NULL, NULL)) == S_OK)
  1952. {
  1953. CSysFreeMe sfm(strName);
  1954. CClearMe cm(&v);
  1955. if(V_VT(&v) == VT_BSTR)
  1956. {
  1957. hres = WriteInstanceReference(wszFilePath, wszClassName, strName,
  1958. V_BSTR(&v));
  1959. if(FAILED(hres))
  1960. return hres;
  1961. }
  1962. }
  1963. if(FAILED(hres))
  1964. return hres;
  1965. pInst->EndEnumeration();
  1966. return S_OK;
  1967. }
  1968. // NOTE: will clobber wszTargetPath
  1969. CHR CNamespaceHandle::ConstructReferenceDir(LPWSTR wszTargetPath,
  1970. LPWSTR wszReferenceDir)
  1971. {
  1972. //
  1973. // Deconstruct the target path name so that we could get a directory
  1974. // for it
  1975. //
  1976. DWORD dwKeySpace = (wcslen(wszTargetPath)+1) * sizeof(WCHAR);
  1977. LPWSTR wszKey = (LPWSTR)TempAlloc(dwKeySpace);
  1978. if(wszKey == NULL)
  1979. return WBEM_E_OUT_OF_MEMORY;
  1980. CTempFreeMe tfm2(wszKey, dwKeySpace);
  1981. LPWSTR wszClassName = NULL;
  1982. LPWSTR wszTargetNamespace = NULL;
  1983. bool bIsClass;
  1984. HRESULT hres = ComputeKeyFromPath(wszTargetPath, wszKey, &wszClassName,
  1985. &bIsClass, &wszTargetNamespace);
  1986. if(FAILED(hres))
  1987. return hres;
  1988. CTempFreeMe tfm1(wszClassName);
  1989. wszTargetPath = NULL; // invalidated by parsing
  1990. CTempFreeMe tfm3(wszTargetNamespace);
  1991. //
  1992. // Check if the target namespace is the same as ours
  1993. //
  1994. CNamespaceHandle* pTargetHandle = NULL;
  1995. if(wszTargetNamespace && wbem_wcsicmp(wszTargetNamespace, m_wsNamespace))
  1996. {
  1997. //
  1998. // It's different --- open it!
  1999. //
  2000. hres = m_pRepository->GetNamespaceHandle(wszTargetNamespace,
  2001. &pTargetHandle);
  2002. if(FAILED(hres))
  2003. {
  2004. ERRORTRACE((LOG_WBEMCORE, "Unable to open target namespace "
  2005. "'%S' in namespace '%S'\n", wszTargetNamespace,
  2006. (LPCWSTR)m_wsNamespace));
  2007. return hres;
  2008. }
  2009. }
  2010. else
  2011. {
  2012. pTargetHandle = this;
  2013. pTargetHandle->AddRef();
  2014. }
  2015. CReleaseMe rm1(pTargetHandle);
  2016. if(bIsClass)
  2017. {
  2018. return pTargetHandle->ConstructReferenceDirFromKey(NULL, wszClassName,
  2019. wszReferenceDir);
  2020. }
  2021. else
  2022. {
  2023. return pTargetHandle->ConstructReferenceDirFromKey(wszClassName, wszKey,
  2024. wszReferenceDir);
  2025. }
  2026. }
  2027. CHR CNamespaceHandle::ConstructReferenceDirFromKey(LPCWSTR wszClassName,
  2028. LPCWSTR wszKey, LPWSTR wszReferenceDir)
  2029. {
  2030. HRESULT hres;
  2031. //
  2032. // Construct the class directory for this instance
  2033. //
  2034. hres = ConstructKeyRootDirFromClass(wszReferenceDir, wszClassName);
  2035. if(FAILED(hres))
  2036. return hres;
  2037. int nLen = wcslen(wszReferenceDir);
  2038. wcscpy(wszReferenceDir+nLen, L"\\" A51_INSTREF_DIR_PREFIX);
  2039. nLen += 1 + wcslen(A51_INSTREF_DIR_PREFIX);
  2040. //
  2041. // Write instance hash
  2042. //
  2043. if(!Hash(wszKey, wszReferenceDir+nLen))
  2044. return WBEM_E_OUT_OF_MEMORY;
  2045. return S_OK;
  2046. }
  2047. // NOTE: will clobber wszReference
  2048. CHR CNamespaceHandle::ConstructReferenceFileName(LPWSTR wszReference,
  2049. LPCWSTR wszReferringFile, LPWSTR wszReferenceFile)
  2050. {
  2051. HRESULT hres = ConstructReferenceDir(wszReference, wszReferenceFile);
  2052. if(FAILED(hres))
  2053. return hres;
  2054. wszReference = NULL; // invalid
  2055. //
  2056. // It is basically
  2057. // irrelevant, we should use a randomly constructed name. Right now, we
  2058. // use a hash of the class name of the referrer --- THIS IS A BUG, THE SAME
  2059. // INSTANCE CAN POINT TO THE SAME ENDPOINT TWICE!!
  2060. //
  2061. wcscat(wszReferenceFile, L"\\"A51_REF_FILE_PREFIX);
  2062. DWORD dwLen = wcslen(wszReferenceFile);
  2063. if (!Hash(wszReferringFile, wszReferenceFile+dwLen))
  2064. return WBEM_E_OUT_OF_MEMORY;
  2065. return S_OK;
  2066. }
  2067. // NOTE: will clobber wszReference
  2068. CHR CNamespaceHandle::WriteInstanceReference(LPCWSTR wszReferringFile,
  2069. LPCWSTR wszReferringClass,
  2070. LPCWSTR wszReferringProp, LPWSTR wszReference)
  2071. {
  2072. HRESULT hres;
  2073. //
  2074. // Figure out the name of the file for the reference.
  2075. //
  2076. CFileName wszReferenceFile;
  2077. if (wszReferenceFile == NULL)
  2078. return WBEM_E_OUT_OF_MEMORY;
  2079. hres = ConstructReferenceFileName(wszReference, wszReferringFile,
  2080. wszReferenceFile);
  2081. if(FAILED(hres))
  2082. {
  2083. if(hres == WBEM_E_NOT_FOUND)
  2084. {
  2085. //
  2086. // Oh joy. A reference to an instance of a *class* that does not
  2087. // exist (not a non-existence instance, those are normal).
  2088. // Forget it (BUGBUG)
  2089. //
  2090. return S_OK;
  2091. }
  2092. else
  2093. return hres;
  2094. }
  2095. //
  2096. // Construct the buffer
  2097. //
  2098. DWORD dwTotalLen = 4 * sizeof(DWORD) +
  2099. (wcslen(wszReferringClass) + wcslen(wszReferringProp) +
  2100. wcslen(wszReferringFile) - g_Glob.GetRootDirLen() +
  2101. wcslen(m_wsNamespace) + 4)
  2102. * sizeof(WCHAR);
  2103. BYTE* pBuffer = (BYTE*)TempAlloc(dwTotalLen);
  2104. if (pBuffer == NULL)
  2105. return WBEM_E_OUT_OF_MEMORY;
  2106. CTempFreeMe vdm(pBuffer, dwTotalLen);
  2107. BYTE* pCurrent = pBuffer;
  2108. DWORD dwStringLen;
  2109. //
  2110. // Write namespace name
  2111. //
  2112. dwStringLen = wcslen(m_wsNamespace);
  2113. memcpy(pCurrent, &dwStringLen, sizeof(DWORD));
  2114. pCurrent += sizeof(DWORD);
  2115. memcpy(pCurrent, m_wsNamespace, sizeof(WCHAR)*dwStringLen);
  2116. pCurrent += sizeof(WCHAR)*dwStringLen;
  2117. //
  2118. // Write the referring class name
  2119. //
  2120. dwStringLen = wcslen(wszReferringClass);
  2121. memcpy(pCurrent, &dwStringLen, sizeof(DWORD));
  2122. pCurrent += sizeof(DWORD);
  2123. memcpy(pCurrent, wszReferringClass, sizeof(WCHAR)*dwStringLen);
  2124. pCurrent += sizeof(WCHAR)*dwStringLen;
  2125. //
  2126. // Write referring property name
  2127. //
  2128. dwStringLen = wcslen(wszReferringProp);
  2129. memcpy(pCurrent, &dwStringLen, sizeof(DWORD));
  2130. pCurrent += sizeof(DWORD);
  2131. memcpy(pCurrent, wszReferringProp, sizeof(WCHAR)*dwStringLen);
  2132. pCurrent += sizeof(WCHAR)*dwStringLen;
  2133. //
  2134. // Write referring file name minus the database root path. Notice that we
  2135. // cannot skip the namespace-specific prefix lest we break cross-namespace
  2136. // associations
  2137. //
  2138. dwStringLen = wcslen(wszReferringFile) - g_Glob.GetRootDirLen();
  2139. memcpy(pCurrent, &dwStringLen, sizeof(DWORD));
  2140. pCurrent += sizeof(DWORD);
  2141. memcpy(pCurrent, wszReferringFile + g_Glob.GetRootDirLen(),
  2142. sizeof(WCHAR)*dwStringLen);
  2143. pCurrent += sizeof(WCHAR)*dwStringLen;
  2144. //
  2145. // All done --- create the file
  2146. //
  2147. long lRes = g_Glob.GetFileCache()->WriteObject(wszReferenceFile, NULL, dwTotalLen,
  2148. pBuffer);
  2149. if(lRes != ERROR_SUCCESS)
  2150. return WBEM_E_FAILED;
  2151. return S_OK;
  2152. }
  2153. CHR CNamespaceHandle::PutClass(_IWmiObject* pClass, DWORD dwFlags,
  2154. CEventCollector &aEvents)
  2155. {
  2156. HRESULT hres;
  2157. bool bDisableEvents = ((dwFlags & WMIDB_DISABLE_EVENTS)?true:false);
  2158. //
  2159. // Get the class name
  2160. //
  2161. VARIANT vClass;
  2162. hres = pClass->Get(L"__CLASS", 0, &vClass, NULL, NULL);
  2163. if(FAILED(hres) || (V_VT(&vClass) != VT_BSTR) ||
  2164. !V_BSTR(&vClass) || !wcslen(V_BSTR(&vClass)))
  2165. {
  2166. return WBEM_E_INVALID_OBJECT;
  2167. }
  2168. CClearMe cm1(&vClass);
  2169. LPCWSTR wszClassName = V_BSTR(&vClass);
  2170. //
  2171. // Check to make sure this class was created from a valid parent class
  2172. //
  2173. VARIANT vSuperClass;
  2174. hres = pClass->Get(L"__SUPERCLASS", 0, &vSuperClass, NULL, NULL);
  2175. if (FAILED(hres))
  2176. return WBEM_E_INVALID_OBJECT;
  2177. CClearMe cm2(&vSuperClass);
  2178. _IWmiObject* pSuperClass = NULL;
  2179. if ((V_VT(&vSuperClass) == VT_BSTR) && V_BSTR(&vSuperClass) &&
  2180. wcslen(V_BSTR(&vSuperClass)))
  2181. {
  2182. LPCWSTR wszSuperClassName = V_BSTR(&vSuperClass);
  2183. // do not clone
  2184. hres = GetClassDirect(wszSuperClassName, IID__IWmiObject,
  2185. (void**)&pSuperClass, false, NULL, NULL, NULL);
  2186. if (hres == WBEM_E_NOT_FOUND)
  2187. return WBEM_E_INVALID_SUPERCLASS;
  2188. if (FAILED(hres))
  2189. return hres;
  2190. if(wszClassName[0] != L'_')
  2191. {
  2192. hres = pClass->IsParentClass(0, pSuperClass);
  2193. if(FAILED(hres))
  2194. return hres;
  2195. if(hres == WBEM_S_FALSE)
  2196. return WBEM_E_INVALID_SUPERCLASS;
  2197. }
  2198. }
  2199. CReleaseMe rm(pSuperClass);
  2200. //
  2201. // Retrieve the previous definition, if any
  2202. //
  2203. _IWmiObject* pOldClass = NULL;
  2204. __int64 nOldTime = 0;
  2205. hres = GetClassDirect(wszClassName, IID__IWmiObject, (void**)&pOldClass,
  2206. false, &nOldTime, NULL, NULL); // do not clone
  2207. if(FAILED(hres) && hres != WBEM_E_NOT_FOUND)
  2208. return hres;
  2209. CReleaseMe rm1(pOldClass);
  2210. if ((dwFlags & WBEM_FLAG_CREATE_ONLY) && (hres != WBEM_E_NOT_FOUND))
  2211. return WBEM_E_ALREADY_EXISTS;
  2212. if ((dwFlags & WBEM_FLAG_UPDATE_ONLY) && (FAILED(hres)))
  2213. return WBEM_E_NOT_FOUND;
  2214. //
  2215. // If the class exists, we need to check the update scenarios to make sure
  2216. // we do not break any
  2217. //
  2218. bool bNoClassChangeDetected = false;
  2219. if (pOldClass)
  2220. {
  2221. hres = pClass->CompareDerivedMostClass(0, pOldClass);
  2222. if ((hres != WBEM_S_FALSE) && (hres != WBEM_S_NO_ERROR))
  2223. return hres;
  2224. else if (hres == WBEM_S_NO_ERROR)
  2225. bNoClassChangeDetected = true;
  2226. }
  2227. A51TRACE(("Putting class %S, dwFlags=0x%X. Old was %p, changed=%d\n",
  2228. wszClassName, dwFlags, pOldClass, !bNoClassChangeDetected));
  2229. if (!bNoClassChangeDetected)
  2230. {
  2231. if (pOldClass != NULL)
  2232. {
  2233. hres = CanClassBeUpdatedCompatible(dwFlags, wszClassName, pOldClass,
  2234. pClass);
  2235. if(FAILED(hres))
  2236. {
  2237. if((dwFlags & WBEM_FLAG_UPDATE_SAFE_MODE) == 0 &&
  2238. (dwFlags & WBEM_FLAG_UPDATE_FORCE_MODE) == 0)
  2239. {
  2240. // Can't compatibly, not allowed any other way
  2241. return hres;
  2242. }
  2243. if(hres != WBEM_E_CLASS_HAS_CHILDREN &&
  2244. hres != WBEM_E_CLASS_HAS_INSTANCES)
  2245. {
  2246. // some serious failure!
  2247. return hres;
  2248. }
  2249. //
  2250. // This is a safe mode or force mode update which takes more
  2251. // than a compatible update to carry out the operation
  2252. //
  2253. return UpdateClassSafeForce(pSuperClass, dwFlags, wszClassName,
  2254. pOldClass, pClass, aEvents);
  2255. }
  2256. }
  2257. //
  2258. // Either there was no previous copy, or it is compatible with the new
  2259. // one, so we can perform a compatible update
  2260. //
  2261. hres = UpdateClassCompatible(pSuperClass, wszClassName, pClass,
  2262. pOldClass, nOldTime);
  2263. if (FAILED(hres))
  2264. return hres;
  2265. }
  2266. if(!bDisableEvents)
  2267. {
  2268. if(pOldClass)
  2269. {
  2270. hres = FireEvent(aEvents, WBEM_EVENTTYPE_ClassModification,
  2271. wszClassName, pClass, pOldClass);
  2272. }
  2273. else
  2274. {
  2275. hres = FireEvent(aEvents, WBEM_EVENTTYPE_ClassCreation,
  2276. wszClassName, pClass);
  2277. }
  2278. }
  2279. return S_OK;
  2280. }
  2281. CHR CNamespaceHandle::UpdateClassCompatible(_IWmiObject* pSuperClass,
  2282. LPCWSTR wszClassName, _IWmiObject *pClass, _IWmiObject *pOldClass,
  2283. __int64 nFakeUpdateTime)
  2284. {
  2285. HRESULT hres;
  2286. //
  2287. // Construct the path for the file
  2288. //
  2289. CFileName wszHash;
  2290. if (wszHash == NULL)
  2291. return WBEM_E_OUT_OF_MEMORY;
  2292. if(!A51Hash(wszClassName, wszHash))
  2293. return WBEM_E_OUT_OF_MEMORY;
  2294. A51TRACE(("Class %S has has %S\n", wszClassName, wszHash));
  2295. return UpdateClassCompatibleHash(pSuperClass, wszHash, pClass, pOldClass,
  2296. nFakeUpdateTime);
  2297. }
  2298. CHR CNamespaceHandle::UpdateClassCompatibleHash(_IWmiObject* pSuperClass,
  2299. LPCWSTR wszClassHash, _IWmiObject *pClass, _IWmiObject *pOldClass,
  2300. __int64 nFakeUpdateTime)
  2301. {
  2302. HRESULT hres;
  2303. CFileName wszFileName;
  2304. CFileName wszFilePath;
  2305. if ((wszFileName == NULL) || (wszFilePath == NULL))
  2306. return WBEM_E_OUT_OF_MEMORY;
  2307. wcscpy(wszFileName, A51_CLASSDEF_FILE_PREFIX);
  2308. wcscat(wszFileName, wszClassHash);
  2309. wcscpy(wszFilePath, m_wszClassRootDir);
  2310. wcscat(wszFilePath, L"\\");
  2311. wcscat(wszFilePath, wszFileName);
  2312. //
  2313. // Write it into the file
  2314. //
  2315. hres = ClassToFile(pSuperClass, pClass, wszFilePath,
  2316. nFakeUpdateTime);
  2317. if(FAILED(hres))
  2318. return hres;
  2319. //
  2320. // Add all needed references --- parent, pointers, etc
  2321. //
  2322. if (pOldClass)
  2323. {
  2324. VARIANT v;
  2325. VariantInit(&v);
  2326. hres = pClass->Get(L"__CLASS", 0, &v, NULL, NULL);
  2327. CClearMe cm(&v);
  2328. if(SUCCEEDED(hres))
  2329. {
  2330. hres = EraseClassRelationships(V_BSTR(&v), pOldClass, wszFileName);
  2331. }
  2332. if (FAILED(hres))
  2333. return hres;
  2334. }
  2335. hres = WriteClassRelationships(pClass, wszFileName);
  2336. return hres;
  2337. }
  2338. CHR CNamespaceHandle::UpdateClassSafeForce(_IWmiObject* pSuperClass,
  2339. DWORD dwFlags, LPCWSTR wszClassName, _IWmiObject *pOldClass,
  2340. _IWmiObject *pNewClass, CEventCollector &aEvents)
  2341. {
  2342. HRESULT hres = UpdateClassAggressively(pSuperClass, dwFlags, wszClassName,
  2343. pNewClass, pOldClass, aEvents);
  2344. //
  2345. // If this is a force mode update and we failed for anything other than
  2346. // out of memory then we should delete the class and try again.
  2347. //
  2348. if (FAILED(hres) &&
  2349. (hres != WBEM_E_OUT_OF_MEMORY) &&
  2350. (hres != WBEM_E_CIRCULAR_REFERENCE) &&
  2351. (hres != WBEM_E_UPDATE_TYPE_MISMATCH) &&
  2352. (dwFlags & WBEM_FLAG_UPDATE_FORCE_MODE))
  2353. {
  2354. //
  2355. // We need to delete the class and try again.
  2356. //
  2357. hres = DeleteClass(wszClassName, aEvents);
  2358. if(FAILED(hres))
  2359. return hres;
  2360. //Write class as though it did not exist
  2361. hres = UpdateClassCompatible(pSuperClass, wszClassName, pNewClass, NULL);
  2362. }
  2363. return hres;
  2364. }
  2365. CHR CNamespaceHandle::UpdateClassAggressively(_IWmiObject* pSuperClass,
  2366. DWORD dwFlags, LPCWSTR wszClassName, _IWmiObject *pNewClass,
  2367. _IWmiObject *pOldClass, CEventCollector &aEvents)
  2368. {
  2369. HRESULT hres = WBEM_S_NO_ERROR;
  2370. if ((dwFlags & WBEM_FLAG_UPDATE_FORCE_MODE) == 0)
  2371. {
  2372. //
  2373. // If we have instances we need to quit as we cannot update them.
  2374. //
  2375. hres = ClassHasInstances(wszClassName);
  2376. if(FAILED(hres))
  2377. return hres;
  2378. if (hres == WBEM_S_NO_ERROR)
  2379. return WBEM_E_CLASS_HAS_INSTANCES;
  2380. _ASSERT(hres == WBEM_S_FALSE, L"Unknown success code!");
  2381. }
  2382. else if (dwFlags & WBEM_FLAG_UPDATE_FORCE_MODE)
  2383. {
  2384. //
  2385. // We need to delete the instances
  2386. //
  2387. hres = DeleteClassInstances(wszClassName, pOldClass, aEvents);
  2388. if(FAILED(hres))
  2389. return hres;
  2390. }
  2391. //
  2392. // Retrieve all child classes and update them
  2393. //
  2394. CWStringArray wsChildHashes;
  2395. hres = GetChildHashes(wszClassName, wsChildHashes);
  2396. if(FAILED(hres))
  2397. return hres;
  2398. for (int i = 0; i != wsChildHashes.Size(); i++)
  2399. {
  2400. hres = UpdateChildClassAggressively(dwFlags, wsChildHashes[i],
  2401. pNewClass, aEvents);
  2402. if (FAILED(hres))
  2403. return hres;
  2404. }
  2405. //
  2406. // Now we need to write the class back, update class refs etc.
  2407. //
  2408. hres = UpdateClassCompatible(pSuperClass, wszClassName, pNewClass,
  2409. pOldClass);
  2410. if(FAILED(hres))
  2411. return hres;
  2412. //
  2413. // Generate the class modification event...
  2414. //
  2415. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  2416. {
  2417. hres = FireEvent(aEvents, WBEM_EVENTTYPE_ClassModification, wszClassName, pNewClass, pOldClass);
  2418. }
  2419. return S_OK;
  2420. }
  2421. CHR CNamespaceHandle::UpdateChildClassAggressively(DWORD dwFlags,
  2422. LPCWSTR wszClassHash, _IWmiObject *pNewParentClass,
  2423. CEventCollector &aEvents)
  2424. {
  2425. HRESULT hres = WBEM_S_NO_ERROR;
  2426. dwFlags &= (WBEM_FLAG_UPDATE_FORCE_MODE | WBEM_FLAG_UPDATE_SAFE_MODE);
  2427. if ((dwFlags & WBEM_FLAG_UPDATE_FORCE_MODE) == 0)
  2428. {
  2429. hres = ClassHasInstancesFromClassHash(wszClassHash);
  2430. if(FAILED(hres))
  2431. return hres;
  2432. if (hres == WBEM_S_NO_ERROR)
  2433. return WBEM_E_CLASS_HAS_INSTANCES;
  2434. _ASSERT(hres == WBEM_S_FALSE, L"Unknown success code!");
  2435. }
  2436. //
  2437. // Get the old class definition
  2438. //
  2439. _IWmiObject *pOldClass = NULL;
  2440. hres = GetClassByHash(wszClassHash, true, &pOldClass, NULL, NULL, NULL);
  2441. if(FAILED(hres))
  2442. return hres;
  2443. CReleaseMe rm1(pOldClass);
  2444. if (dwFlags & WBEM_FLAG_UPDATE_FORCE_MODE)
  2445. {
  2446. //
  2447. // Need to delete all its instances, if any
  2448. //
  2449. VARIANT v;
  2450. VariantInit(&v);
  2451. hres = pOldClass->Get(L"__CLASS", 0, &v, NULL, NULL);
  2452. if(FAILED(hres))
  2453. return hres;
  2454. CClearMe cm(&v);
  2455. hres = DeleteClassInstances(V_BSTR(&v), pOldClass, aEvents);
  2456. if(FAILED(hres))
  2457. return hres;
  2458. }
  2459. //
  2460. // Update the existing class definition to work with the new parent class
  2461. //
  2462. _IWmiObject *pNewClass = NULL;
  2463. hres = pNewParentClass->Update(pOldClass, dwFlags, &pNewClass);
  2464. if(FAILED(hres))
  2465. return hres;
  2466. CReleaseMe rm2(pNewClass);
  2467. //
  2468. // Now we have to recurse through all child classes and do the same
  2469. //
  2470. CWStringArray wsChildHashes;
  2471. hres = GetChildHashesByHash(wszClassHash, wsChildHashes);
  2472. if(FAILED(hres))
  2473. return hres;
  2474. for (int i = 0; i != wsChildHashes.Size(); i++)
  2475. {
  2476. hres = UpdateChildClassAggressively(dwFlags, wsChildHashes[i],
  2477. pNewClass, aEvents);
  2478. if (FAILED(hres))
  2479. return hres;
  2480. }
  2481. //
  2482. // Now we need to write the class back, update class refs etc
  2483. //
  2484. hres = UpdateClassCompatibleHash(pNewParentClass, wszClassHash,
  2485. pNewClass, pOldClass);
  2486. if(FAILED(hres))
  2487. return hres;
  2488. return S_OK;
  2489. }
  2490. CHR CNamespaceHandle::CanClassBeUpdatedCompatible(DWORD dwFlags,
  2491. LPCWSTR wszClassName, _IWmiObject *pOldClass, _IWmiObject *pNewClass)
  2492. {
  2493. HRESULT hres;
  2494. HRESULT hresError = WBEM_S_NO_ERROR;
  2495. //
  2496. // Do we have subclasses?
  2497. //
  2498. hres = ClassHasChildren(wszClassName);
  2499. if(FAILED(hres))
  2500. return hres;
  2501. if(hres == WBEM_S_NO_ERROR)
  2502. {
  2503. hresError = WBEM_E_CLASS_HAS_CHILDREN;
  2504. }
  2505. else
  2506. {
  2507. _ASSERT(hres == WBEM_S_FALSE, L"Unknown success code");
  2508. //
  2509. // Do we have instances belonging to this class? Don't even need to
  2510. // worry about sub-classes because we know we have none at this point!
  2511. //
  2512. hres = ClassHasInstances(wszClassName);
  2513. if(FAILED(hres))
  2514. return hres;
  2515. if(hres == WBEM_S_NO_ERROR)
  2516. {
  2517. hresError = WBEM_E_CLASS_HAS_INSTANCES;
  2518. }
  2519. else
  2520. {
  2521. _ASSERT(hres == WBEM_S_FALSE, L"Unknown success code");
  2522. //
  2523. // No nothing!
  2524. //
  2525. return WBEM_S_NO_ERROR;
  2526. }
  2527. }
  2528. _ASSERT(hresError != WBEM_S_NO_ERROR, L"");
  2529. //
  2530. // We have either subclasses or instances.
  2531. // Can we reconcile this class safely?
  2532. //
  2533. hres = pOldClass->ReconcileWith(
  2534. WMIOBJECT_RECONCILE_FLAG_TESTRECONCILE, pNewClass);
  2535. if(hres == WBEM_S_NO_ERROR)
  2536. {
  2537. // reconcilable, so OK
  2538. return WBEM_S_NO_ERROR;
  2539. }
  2540. else if(hres == WBEM_E_FAILED) // awful, isn't it
  2541. {
  2542. // irreconcilable
  2543. return hresError;
  2544. }
  2545. else
  2546. {
  2547. return hres;
  2548. }
  2549. }
  2550. CHR CNamespaceHandle::FireEvent(CEventCollector &aEvents,
  2551. DWORD dwType, LPCWSTR wszArg1,
  2552. _IWmiObject* pObj1, _IWmiObject* pObj2)
  2553. {
  2554. try
  2555. {
  2556. CRepEvent *pEvent = new CRepEvent(dwType, m_wsFullNamespace, wszArg1,
  2557. pObj1, pObj2);
  2558. if (pEvent == NULL)
  2559. return WBEM_E_OUT_OF_MEMORY;
  2560. if (!aEvents.AddEvent(pEvent))
  2561. {
  2562. delete pEvent;
  2563. return WBEM_E_OUT_OF_MEMORY;
  2564. }
  2565. return WBEM_S_NO_ERROR;
  2566. }
  2567. catch (CX_MemoryException)
  2568. {
  2569. return WBEM_E_OUT_OF_MEMORY;
  2570. }
  2571. }
  2572. HRESULT CNamespaceHandle::SendEvents(CEventCollector &aEvents)
  2573. {
  2574. _IWmiCoreServices * pSvcs = g_Glob.GetCoreSvcs();
  2575. CReleaseMe rm(pSvcs);
  2576. aEvents.SendEvents(pSvcs);
  2577. //
  2578. // Ignore ESS return codes --- they do not invalidate the operation
  2579. //
  2580. return WBEM_S_NO_ERROR;
  2581. }
  2582. CHR CNamespaceHandle::WriteClassRelationships(_IWmiObject* pClass,
  2583. LPCWSTR wszFileName)
  2584. {
  2585. HRESULT hres;
  2586. //
  2587. // Get the parent
  2588. //
  2589. VARIANT v;
  2590. VariantInit(&v);
  2591. hres = pClass->Get(L"__SUPERCLASS", 0, &v, NULL, NULL);
  2592. CClearMe cm(&v);
  2593. if(FAILED(hres))
  2594. return hres;
  2595. if(V_VT(&v) == VT_BSTR)
  2596. hres = WriteParentChildRelationship(wszFileName, V_BSTR(&v));
  2597. else
  2598. hres = WriteParentChildRelationship(wszFileName, L"");
  2599. if(FAILED(hres))
  2600. return hres;
  2601. //
  2602. // Write references
  2603. //
  2604. hres = pClass->BeginEnumeration(WBEM_FLAG_REFS_ONLY);
  2605. if(FAILED(hres))
  2606. return hres;
  2607. BSTR strName = NULL;
  2608. while((hres = pClass->Next(0, &strName, NULL, NULL, NULL)) == S_OK)
  2609. {
  2610. CSysFreeMe sfm(strName);
  2611. hres = WriteClassReference(pClass, wszFileName, strName);
  2612. if(FAILED(hres))
  2613. return hres;
  2614. }
  2615. pClass->EndEnumeration();
  2616. if(FAILED(hres))
  2617. return hres;
  2618. return S_OK;
  2619. }
  2620. CHR CNamespaceHandle::WriteClassReference(_IWmiObject* pReferringClass,
  2621. LPCWSTR wszReferringFile,
  2622. LPCWSTR wszReferringProp)
  2623. {
  2624. HRESULT hres;
  2625. //
  2626. // Figure out the class we are pointing to
  2627. //
  2628. DWORD dwSize = 0;
  2629. DWORD dwFlavor = 0;
  2630. CIMTYPE ct;
  2631. hres = pReferringClass->GetPropQual(wszReferringProp, L"CIMTYPE", 0, 0,
  2632. &ct, &dwFlavor, &dwSize, NULL);
  2633. if(dwSize == 0)
  2634. return WBEM_E_OUT_OF_MEMORY;
  2635. LPWSTR wszQual = (WCHAR*)TempAlloc(dwSize);
  2636. if(wszQual == NULL)
  2637. return WBEM_E_OUT_OF_MEMORY;
  2638. CTempFreeMe tfm(wszQual, dwSize);
  2639. hres = pReferringClass->GetPropQual(wszReferringProp, L"CIMTYPE", 0, dwSize,
  2640. &ct, &dwFlavor, &dwSize, wszQual);
  2641. if(FAILED(hres))
  2642. return hres;
  2643. //
  2644. // Parse out the class name
  2645. //
  2646. WCHAR* pwcColon = wcschr(wszQual, L':');
  2647. if(pwcColon == NULL)
  2648. return S_OK; // untyped reference requires no bookkeeping
  2649. LPCWSTR wszReferredToClass = pwcColon+1;
  2650. //
  2651. // Figure out the name of the file for the reference.
  2652. //
  2653. CFileName wszReferenceFile;
  2654. if (wszReferenceFile == NULL)
  2655. return WBEM_E_OUT_OF_MEMORY;
  2656. hres = ConstructClassReferenceFileName(wszReferredToClass,
  2657. wszReferringFile, wszReferringProp,
  2658. wszReferenceFile);
  2659. if(FAILED(hres))
  2660. return hres;
  2661. //
  2662. // Create the empty file
  2663. //
  2664. long lRes = g_Glob.GetFileCache()->WriteLink(wszReferenceFile);
  2665. if(lRes != ERROR_SUCCESS)
  2666. return WBEM_E_FAILED;
  2667. return S_OK;
  2668. }
  2669. CHR CNamespaceHandle::WriteParentChildRelationship(
  2670. LPCWSTR wszChildFileName, LPCWSTR wszParentName)
  2671. {
  2672. CFileName wszParentChildFileName;
  2673. if (wszParentChildFileName == NULL)
  2674. return WBEM_E_OUT_OF_MEMORY;
  2675. HRESULT hres = ConstructParentChildFileName(wszChildFileName,
  2676. wszParentName,
  2677. wszParentChildFileName);
  2678. //
  2679. // Create the file
  2680. //
  2681. long lRes = g_Glob.GetFileCache()->WriteLink(wszParentChildFileName);
  2682. if(lRes != ERROR_SUCCESS)
  2683. return WBEM_E_FAILED;
  2684. return S_OK;
  2685. }
  2686. CHR CNamespaceHandle::ConstructParentChildFileName(
  2687. LPCWSTR wszChildFileName, LPCWSTR wszParentName,
  2688. LPWSTR wszParentChildFileName)
  2689. {
  2690. //
  2691. // Construct the name of the directory where the parent class keeps its
  2692. // children
  2693. //
  2694. HRESULT hres = ConstructClassRelationshipsDir(wszParentName,
  2695. wszParentChildFileName);
  2696. if(FAILED(hres))
  2697. return hres;
  2698. //
  2699. // Append the filename of the child, but substituting the child-class prefix
  2700. // for the class-def prefix
  2701. //
  2702. wcscat(wszParentChildFileName, L"\\" A51_CHILDCLASS_FILE_PREFIX);
  2703. wcscat(wszParentChildFileName,
  2704. wszChildFileName + wcslen(A51_CLASSDEF_FILE_PREFIX));
  2705. return S_OK;
  2706. }
  2707. CHR CNamespaceHandle::ConstructClassRelationshipsDir(LPCWSTR wszClassName,
  2708. LPWSTR wszDirPath)
  2709. {
  2710. wcscpy(wszDirPath, m_wszClassRootDir);
  2711. wcscpy(wszDirPath + m_lClassRootDirLen, L"\\" A51_CLASSRELATION_DIR_PREFIX);
  2712. if(!Hash(wszClassName,
  2713. wszDirPath + m_lClassRootDirLen + 1 + wcslen(A51_CLASSRELATION_DIR_PREFIX)))
  2714. {
  2715. return WBEM_E_OUT_OF_MEMORY;
  2716. }
  2717. return S_OK;
  2718. }
  2719. CHR CNamespaceHandle::ConstructClassRelationshipsDirFromHash(
  2720. LPCWSTR wszHash, LPWSTR wszDirPath)
  2721. {
  2722. wcscpy(wszDirPath, m_wszClassRootDir);
  2723. wcscpy(wszDirPath + m_lClassRootDirLen, L"\\" A51_CLASSRELATION_DIR_PREFIX);
  2724. wcscpy(wszDirPath + m_lClassRootDirLen + 1 +wcslen(A51_CLASSRELATION_DIR_PREFIX),
  2725. wszHash);
  2726. return S_OK;
  2727. }
  2728. CHR CNamespaceHandle::ConstructClassReferenceFileName(
  2729. LPCWSTR wszReferredToClass,
  2730. LPCWSTR wszReferringFile,
  2731. LPCWSTR wszReferringProp,
  2732. LPWSTR wszFileName)
  2733. {
  2734. HRESULT hres;
  2735. hres = ConstructClassRelationshipsDir(wszReferredToClass, wszFileName);
  2736. if(FAILED(hres))
  2737. return hres;
  2738. //
  2739. // Extract the portion of the referring file containing the class hash
  2740. //
  2741. WCHAR* pwcLastUnderscore = wcsrchr(wszReferringFile, L'_');
  2742. if(pwcLastUnderscore == NULL)
  2743. return WBEM_E_CRITICAL_ERROR;
  2744. LPCWSTR wszReferringClassHash = pwcLastUnderscore+1;
  2745. wcscat(wszFileName, L"\\" A51_REF_FILE_PREFIX);
  2746. wcscat(wszFileName, wszReferringClassHash);
  2747. return S_OK;
  2748. }
  2749. CHR CNamespaceHandle::DeleteObject(
  2750. DWORD dwFlags,
  2751. REFIID riid,
  2752. LPVOID pObj,
  2753. CEventCollector &aEvents
  2754. )
  2755. {
  2756. DebugBreak();
  2757. return E_NOTIMPL;
  2758. }
  2759. CHR CNamespaceHandle::DeleteObjectByPath(DWORD dwFlags, LPWSTR wszPath,
  2760. CEventCollector &aEvents)
  2761. {
  2762. HRESULT hres;
  2763. //
  2764. // Get the key from path
  2765. //
  2766. DWORD dwLen = wcslen(wszPath)*sizeof(WCHAR)+2;
  2767. LPWSTR wszKey = (WCHAR*)TempAlloc(dwLen);
  2768. if(wszKey == NULL)
  2769. return WBEM_E_OUT_OF_MEMORY;
  2770. CTempFreeMe tfm(wszKey, dwLen);
  2771. bool bIsClass;
  2772. LPWSTR wszClassName = NULL;
  2773. hres = ComputeKeyFromPath(wszPath, wszKey, &wszClassName, &bIsClass);
  2774. if(FAILED(hres))
  2775. return hres;
  2776. CTempFreeMe tfm1(wszClassName, (wcslen(wszClassName)+1) * sizeof(WCHAR*));
  2777. if(bIsClass)
  2778. {
  2779. return DeleteClass(wszClassName, aEvents);
  2780. }
  2781. else
  2782. {
  2783. return DeleteInstance(wszClassName, wszKey, aEvents);
  2784. }
  2785. }
  2786. CHR CNamespaceHandle::DeleteInstance(LPCWSTR wszClassName, LPCWSTR wszKey,
  2787. CEventCollector &aEvents)
  2788. {
  2789. HRESULT hres;
  2790. //
  2791. // Get Class definition
  2792. //
  2793. _IWmiObject* pClass = NULL;
  2794. hres = GetClassDirect(wszClassName, IID__IWmiObject, (void**)&pClass,
  2795. false, NULL, NULL, NULL);
  2796. if(FAILED(hres))
  2797. return hres;
  2798. CReleaseMe rm1(pClass);
  2799. //
  2800. // Create its directory
  2801. //
  2802. CFileName wszFilePath;
  2803. if (wszFilePath == NULL)
  2804. return WBEM_E_OUT_OF_MEMORY;
  2805. hres = ConstructKeyRootDirFromClass(wszFilePath, wszClassName);
  2806. if(FAILED(hres))
  2807. return hres;
  2808. //
  2809. // Construct the path for the file
  2810. //
  2811. CFileName wszFileName;
  2812. if (wszFileName == NULL)
  2813. return WBEM_E_OUT_OF_MEMORY;
  2814. hres = ConstructInstanceDefName(wszFileName, wszKey);
  2815. if(FAILED(hres))
  2816. return hres;
  2817. wcscat(wszFilePath, L"\\");
  2818. wcscat(wszFilePath, wszFileName);
  2819. _IWmiObject* pInst;
  2820. hres = FileToInstance(NULL, wszFilePath, NULL, 0, &pInst);
  2821. if(FAILED(hres))
  2822. return hres;
  2823. CReleaseMe rm2(pInst);
  2824. if(pInst->InheritsFrom(L"__Namespace") == S_OK)
  2825. {
  2826. //Make sure this is not a deletion of the root\default namespace
  2827. VARIANT vName;
  2828. VariantInit(&vName);
  2829. CClearMe cm1(&vName);
  2830. hres = pInst->Get(L"Name", 0, &vName, NULL, NULL);
  2831. if(FAILED(hres))
  2832. return WBEM_E_INVALID_OBJECT;
  2833. LPCWSTR wszName = V_BSTR(&vName);
  2834. if ((_wcsicmp(m_wsFullNamespace, L"\\\\.\\root") == 0) && (_wcsicmp(wszName, L"default") == 0))
  2835. return WBEM_E_ACCESS_DENIED;
  2836. }
  2837. hres = DeleteInstanceByFile(wszFilePath, pInst, false, aEvents);
  2838. if(FAILED(hres))
  2839. return hres;
  2840. //
  2841. // Fire an event
  2842. //
  2843. if(pInst->InheritsFrom(L"__Namespace") == S_OK)
  2844. {
  2845. //
  2846. // There is no need to do anything --- deletion of namespaces
  2847. // automatically fires events in DeleteInstanceByFile (because we need
  2848. // to accomplish it in the case of deleting a class derived from
  2849. // __NAMESPACE.
  2850. //
  2851. }
  2852. else
  2853. {
  2854. hres = FireEvent(aEvents, WBEM_EVENTTYPE_InstanceDeletion, wszClassName,
  2855. pInst);
  2856. }
  2857. A51TRACE(("DeleteInstance for class %S succeeded\n", wszClassName));
  2858. return S_OK;
  2859. }
  2860. CHR CNamespaceHandle::DeleteInstanceByFile(LPCWSTR wszFilePath,
  2861. _IWmiObject* pInst, bool bClassDeletion,
  2862. CEventCollector &aEvents)
  2863. {
  2864. HRESULT hres;
  2865. hres = DeleteInstanceSelf(wszFilePath, pInst, bClassDeletion);
  2866. if(FAILED(hres))
  2867. return hres;
  2868. hres = DeleteInstanceAsScope(pInst, aEvents);
  2869. if(FAILED(hres) && hres != WBEM_E_NOT_FOUND)
  2870. {
  2871. return hres;
  2872. }
  2873. return S_OK;
  2874. }
  2875. CHR CNamespaceHandle::DeleteInstanceSelf(LPCWSTR wszFilePath,
  2876. _IWmiObject* pInst,
  2877. bool bClassDeletion)
  2878. {
  2879. HRESULT hres;
  2880. //
  2881. // Delete the file
  2882. //
  2883. long lRes = g_Glob.GetFileCache()->DeleteObject(wszFilePath);
  2884. if(lRes == ERROR_FILE_NOT_FOUND || lRes == ERROR_PATH_NOT_FOUND)
  2885. {
  2886. return WBEM_E_NOT_FOUND;
  2887. }
  2888. else if(lRes != ERROR_SUCCESS)
  2889. return WBEM_E_FAILED;
  2890. hres = DeleteInstanceLink(pInst, wszFilePath);
  2891. if(FAILED(hres) && hres != WBEM_E_NOT_FOUND)
  2892. return hres;
  2893. hres = DeleteInstanceReferences(pInst, wszFilePath);
  2894. if(FAILED(hres) && hres != WBEM_E_NOT_FOUND)
  2895. return hres;
  2896. if(bClassDeletion)
  2897. {
  2898. //
  2899. // We need to remove all dangling references to this instance,
  2900. // because they make no sense once the class is deleted --- we don't
  2901. // know what key structure the new class will even have. In the future,
  2902. // we'll want to move these references to some class-wide location
  2903. //
  2904. hres = DeleteInstanceBackReferences(wszFilePath);
  2905. if(FAILED(hres) && hres != WBEM_E_NOT_FOUND)
  2906. return hres;
  2907. }
  2908. return S_OK;
  2909. }
  2910. CHR CNamespaceHandle::ConstructReferenceDirFromFilePath(
  2911. LPCWSTR wszFilePath, LPWSTR wszReferenceDir)
  2912. {
  2913. //
  2914. // It's the same, only with INSTDEF_FILE_PREFIX replaced with
  2915. // INSTREF_DIR_PREFIX
  2916. //
  2917. CFileName wszEnding;
  2918. if (wszEnding == NULL)
  2919. return WBEM_E_OUT_OF_MEMORY;
  2920. WCHAR* pwcLastSlash = wcsrchr(wszFilePath, L'\\');
  2921. if(pwcLastSlash == NULL)
  2922. return WBEM_E_FAILED;
  2923. wcscpy(wszEnding, pwcLastSlash + 1 + wcslen(A51_INSTDEF_FILE_PREFIX));
  2924. wcscpy(wszReferenceDir, wszFilePath);
  2925. wszReferenceDir[(pwcLastSlash+1)-wszFilePath] = 0;
  2926. wcscat(wszReferenceDir, A51_INSTREF_DIR_PREFIX);
  2927. wcscat(wszReferenceDir, wszEnding);
  2928. return S_OK;
  2929. }
  2930. CHR CNamespaceHandle::DeleteInstanceBackReferences(LPCWSTR wszFilePath)
  2931. {
  2932. HRESULT hres;
  2933. CFileName wszReferenceDir;
  2934. if (wszReferenceDir == NULL)
  2935. return WBEM_E_OUT_OF_MEMORY;
  2936. hres = ConstructReferenceDirFromFilePath(wszFilePath, wszReferenceDir);
  2937. if(FAILED(hres))
  2938. return hres;
  2939. wcscat(wszReferenceDir, L"\\");
  2940. CFileName wszReferencePrefix;
  2941. if (wszReferencePrefix == NULL)
  2942. return WBEM_E_OUT_OF_MEMORY;
  2943. wcscpy(wszReferencePrefix, wszReferenceDir);
  2944. wcscat(wszReferencePrefix, A51_REF_FILE_PREFIX);
  2945. // Prepare a buffer for file path
  2946. CFileName wszFullFileName;
  2947. if (wszFullFileName == NULL)
  2948. return WBEM_E_OUT_OF_MEMORY;
  2949. wcscpy(wszFullFileName, wszReferenceDir);
  2950. long lDirLen = wcslen(wszFullFileName);
  2951. CFileName wszFileName;
  2952. if (wszFileName == NULL)
  2953. return WBEM_E_OUT_OF_MEMORY;
  2954. // Enumerate all files in it
  2955. void* hSearch;
  2956. long lRes = g_Glob.GetFileCache()->IndexEnumerationBegin(wszReferencePrefix, &hSearch);
  2957. if (lRes == ERROR_FILE_NOT_FOUND)
  2958. return ERROR_SUCCESS;
  2959. else if (lRes != ERROR_SUCCESS)
  2960. return A51TranslateErrorCode(lRes);
  2961. while ((lRes = g_Glob.GetFileCache()->IndexEnumerationNext(hSearch, wszFileName)) == ERROR_SUCCESS)
  2962. {
  2963. wcscpy(wszFullFileName+lDirLen, wszFileName);
  2964. lRes = g_Glob.GetFileCache()->DeleteObject(wszFullFileName);
  2965. if(lRes != ERROR_SUCCESS)
  2966. {
  2967. ERRORTRACE((LOG_WBEMCORE, "Cannot delete reference file '%S' with "
  2968. "error code %d\n", wszFullFileName, lRes));
  2969. lRes = ERROR_INVALID_OPERATION; //trigger the correct error!
  2970. }
  2971. }
  2972. g_Glob.GetFileCache()->IndexEnumerationEnd(hSearch);
  2973. if(lRes == ERROR_NO_MORE_FILES)
  2974. {
  2975. return WBEM_S_NO_ERROR;
  2976. }
  2977. else if(lRes != ERROR_SUCCESS)
  2978. {
  2979. return WBEM_E_FAILED;
  2980. }
  2981. return S_OK;
  2982. }
  2983. CHR CNamespaceHandle::DeleteInstanceLink(_IWmiObject* pInst,
  2984. LPCWSTR wszInstanceDefFilePath)
  2985. {
  2986. HRESULT hres;
  2987. //
  2988. // Get the class name
  2989. //
  2990. VARIANT vClass;
  2991. VariantInit(&vClass);
  2992. CClearMe cm1(&vClass);
  2993. hres = pInst->Get(L"__CLASS", 0, &vClass, NULL, NULL);
  2994. if(FAILED(hres))
  2995. return WBEM_E_INVALID_OBJECT;
  2996. LPCWSTR wszClassName = V_BSTR(&vClass);
  2997. //
  2998. // Construct the link directory for the class
  2999. //
  3000. CFileName wszInstanceLinkPath;
  3001. if (wszInstanceLinkPath == NULL)
  3002. return WBEM_E_OUT_OF_MEMORY;
  3003. hres = ConstructLinkDirFromClass(wszInstanceLinkPath, wszClassName);
  3004. if(FAILED(hres))
  3005. return hres;
  3006. wcscat(wszInstanceLinkPath, L"\\" A51_INSTLINK_FILE_PREFIX);
  3007. //
  3008. // It remains to append the instance-specific part of the file name.
  3009. // Convineintly, it is the same material as was used for the def file path,
  3010. // so we can steal it. ALERT: RELIES ON ALL PREFIXES ENDING IN '_'!!
  3011. //
  3012. WCHAR* pwcLastUnderscore = wcsrchr(wszInstanceDefFilePath, L'_');
  3013. if(pwcLastUnderscore == NULL)
  3014. return WBEM_E_CRITICAL_ERROR;
  3015. wcscat(wszInstanceLinkPath, pwcLastUnderscore+1);
  3016. //
  3017. // Delete the file
  3018. //
  3019. long lRes = g_Glob.GetFileCache()->DeleteLink(wszInstanceLinkPath);
  3020. if(lRes == ERROR_FILE_NOT_FOUND || lRes == ERROR_PATH_NOT_FOUND)
  3021. return WBEM_E_NOT_FOUND;
  3022. else if(lRes != ERROR_SUCCESS)
  3023. return WBEM_E_FAILED;
  3024. return S_OK;
  3025. }
  3026. CHR CNamespaceHandle::DeleteInstanceAsScope(_IWmiObject* pInst, CEventCollector &aEvents)
  3027. {
  3028. HRESULT hres;
  3029. //
  3030. // For now, just check if it is a namespace
  3031. //
  3032. hres = pInst->InheritsFrom(L"__Namespace");
  3033. if(FAILED(hres))
  3034. return hres;
  3035. if(hres != S_OK) // not a namespace
  3036. return S_FALSE;
  3037. //
  3038. // It is a namespace --- construct full path
  3039. //
  3040. WString wsFullName = m_wsNamespace;
  3041. wsFullName += L"\\";
  3042. VARIANT vName;
  3043. VariantInit(&vName);
  3044. CClearMe cm(&vName);
  3045. hres = pInst->Get(L"Name", 0, &vName, NULL, NULL);
  3046. if(FAILED(hres))
  3047. return hres;
  3048. if(V_VT(&vName) != VT_BSTR)
  3049. return WBEM_E_INVALID_OBJECT;
  3050. wsFullName += V_BSTR(&vName);
  3051. //
  3052. // Delete it
  3053. //
  3054. CNamespaceHandle* pNewHandle = new CNamespaceHandle(m_pControl,
  3055. m_pRepository);
  3056. if(pNewHandle == NULL)
  3057. return WBEM_E_OUT_OF_MEMORY;
  3058. pNewHandle->AddRef();
  3059. CReleaseMe rm1(pNewHandle);
  3060. hres = pNewHandle->Initialize(wsFullName);
  3061. if(FAILED(hres))
  3062. return hres;
  3063. //
  3064. // Mind to only fire child namespace deletion events from the inside
  3065. //
  3066. bool bNamespaceOnly = aEvents.IsNamespaceOnly();
  3067. aEvents.SetNamespaceOnly(true);
  3068. hres = pNewHandle->DeleteSelf(aEvents);
  3069. if(FAILED(hres))
  3070. return hres;
  3071. aEvents.SetNamespaceOnly(bNamespaceOnly);
  3072. //
  3073. // Fire the event
  3074. //
  3075. hres = FireEvent(aEvents, WBEM_EVENTTYPE_NamespaceDeletion,
  3076. V_BSTR(&vName), pInst);
  3077. return S_OK;
  3078. }
  3079. CHR CNamespaceHandle::DeleteSelf(CEventCollector &aEvents)
  3080. {
  3081. //
  3082. // Delete all top-level classes. This will delete all namespaces
  3083. // (as instances of __Namespace), all classes (as children of top-levels)
  3084. // and all instances
  3085. //
  3086. HRESULT hres = DeleteDerivedClasses(L"", aEvents);
  3087. if(FAILED(hres))
  3088. return hres;
  3089. //
  3090. // We do not delete our class root directory --- if we are a namespace, it
  3091. // is the same as our instance root directory so we are already done; if not
  3092. // we should not be cleaning up all the classes!
  3093. //
  3094. m_pClassCache->SetError(WBEM_E_INVALID_NAMESPACE);
  3095. return S_OK;
  3096. }
  3097. CHR CNamespaceHandle::DeleteInstanceReferences(_IWmiObject* pInst,
  3098. LPCWSTR wszFilePath)
  3099. {
  3100. HRESULT hres;
  3101. hres = pInst->BeginEnumeration(WBEM_FLAG_REFS_ONLY);
  3102. if(FAILED(hres))
  3103. return hres;
  3104. VARIANT v;
  3105. while((hres = pInst->Next(0, NULL, &v, NULL, NULL)) == S_OK)
  3106. {
  3107. CClearMe cm(&v);
  3108. if(V_VT(&v) == VT_BSTR)
  3109. {
  3110. hres = DeleteInstanceReference(wszFilePath, V_BSTR(&v));
  3111. if(FAILED(hres))
  3112. return hres;
  3113. }
  3114. }
  3115. if(FAILED(hres))
  3116. return hres;
  3117. pInst->EndEnumeration();
  3118. return S_OK;
  3119. }
  3120. // NOTE: will clobber wszReference
  3121. CHR CNamespaceHandle::DeleteInstanceReference(LPCWSTR wszOurFilePath,
  3122. LPWSTR wszReference)
  3123. {
  3124. HRESULT hres;
  3125. CFileName wszReferenceFile;
  3126. if (wszReferenceFile == NULL)
  3127. return WBEM_E_OUT_OF_MEMORY;
  3128. hres = ConstructReferenceFileName(wszReference, wszOurFilePath, wszReferenceFile);
  3129. if(FAILED(hres))
  3130. {
  3131. if(hres == WBEM_E_NOT_FOUND)
  3132. {
  3133. //
  3134. // Oh joy. A reference to an instance of a *class* that does not
  3135. // exist (not a non-existence instance, those are normal).
  3136. // Forget it (BUGBUG)
  3137. //
  3138. return S_OK;
  3139. }
  3140. else
  3141. return hres;
  3142. }
  3143. long lRes = g_Glob.GetFileCache()->DeleteObject(wszReferenceFile);
  3144. if(lRes != ERROR_SUCCESS)
  3145. {
  3146. if(lRes == ERROR_FILE_NOT_FOUND)
  3147. return WBEM_E_NOT_FOUND;
  3148. else
  3149. return WBEM_E_FAILED;
  3150. }
  3151. else
  3152. return WBEM_S_NO_ERROR;
  3153. }
  3154. CHR CNamespaceHandle::DeleteClassByHash(LPCWSTR wszHash, CEventCollector &aEvents)
  3155. {
  3156. HRESULT hres;
  3157. //
  3158. // Get Class definition
  3159. //
  3160. _IWmiObject* pClass = NULL;
  3161. bool bSystemClass = false;
  3162. hres = GetClassByHash(wszHash, false, &pClass, NULL, NULL, &bSystemClass);
  3163. CReleaseMe rm1(pClass);
  3164. if(FAILED(hres))
  3165. return hres;
  3166. //
  3167. // Get the actual class name
  3168. //
  3169. VARIANT v;
  3170. hres = pClass->Get(L"__CLASS", 0, &v, NULL, NULL);
  3171. if(FAILED(hres))
  3172. return hres;
  3173. CClearMe cm1(&v);
  3174. if(V_VT(&v) != VT_BSTR)
  3175. return WBEM_E_INVALID_CLASS;
  3176. //
  3177. // Construct definition file name
  3178. //
  3179. CFileName wszFileName;
  3180. if (wszFileName == NULL)
  3181. return WBEM_E_OUT_OF_MEMORY;
  3182. hres = ConstructClassDefFileNameFromHash(wszHash, wszFileName);
  3183. if(FAILED(hres))
  3184. return hres;
  3185. return DeleteClassInternal(V_BSTR(&v), pClass, wszFileName, aEvents, bSystemClass);
  3186. }
  3187. CHR CNamespaceHandle::DeleteClass(LPCWSTR wszClassName, CEventCollector &aEvents)
  3188. {
  3189. HRESULT hres;
  3190. A51TRACE(("Deleting class %S\n", wszClassName));
  3191. //
  3192. // Construct the path for the file
  3193. //
  3194. CFileName wszFileName;
  3195. if (wszFileName == NULL)
  3196. return WBEM_E_OUT_OF_MEMORY;
  3197. hres = ConstructClassDefFileName(wszClassName, wszFileName);
  3198. if(FAILED(hres))
  3199. return hres;
  3200. //
  3201. // Get Class definition
  3202. //
  3203. _IWmiObject* pClass = NULL;
  3204. bool bSystemClass = false;
  3205. hres = GetClassDirect(wszClassName, IID__IWmiObject, (void**)&pClass,
  3206. false, NULL, NULL, &bSystemClass);
  3207. if(FAILED(hres))
  3208. return hres;
  3209. CReleaseMe rm1(pClass);
  3210. return DeleteClassInternal(wszClassName, pClass, wszFileName, aEvents, bSystemClass);
  3211. }
  3212. CHR CNamespaceHandle::DeleteClassInternal(LPCWSTR wszClassName,
  3213. _IWmiObject* pClass,
  3214. LPCWSTR wszFileName,
  3215. CEventCollector &aEvents,
  3216. bool bSystemClass)
  3217. {
  3218. HRESULT hres;
  3219. CFileName wszFilePath;
  3220. if (wszFilePath == NULL)
  3221. return WBEM_E_OUT_OF_MEMORY;
  3222. swprintf(wszFilePath, L"%s\\%s", m_wszClassRootDir, wszFileName);
  3223. //
  3224. // Delete all derived classes
  3225. //
  3226. hres = DeleteDerivedClasses(wszClassName, aEvents);
  3227. if(FAILED(hres))
  3228. return hres;
  3229. //
  3230. // Delete all instances. Only fire events if namespaces are deleted
  3231. //
  3232. bool bNamespaceOnly = aEvents.IsNamespaceOnly();
  3233. aEvents.SetNamespaceOnly(true);
  3234. hres = DeleteClassInstances(wszClassName, pClass, aEvents);
  3235. if(FAILED(hres))
  3236. return hres;
  3237. aEvents.SetNamespaceOnly(bNamespaceOnly);
  3238. if (!bSystemClass)
  3239. {
  3240. //
  3241. // Clean up references
  3242. //
  3243. hres = EraseClassRelationships(wszClassName, pClass, wszFileName);
  3244. if(FAILED(hres))
  3245. return hres;
  3246. //
  3247. // Delete the file
  3248. //
  3249. long lRes = g_Glob.GetFileCache()->DeleteObject(wszFilePath);
  3250. if(lRes == ERROR_FILE_NOT_FOUND || lRes == ERROR_PATH_NOT_FOUND)
  3251. return WBEM_E_NOT_FOUND;
  3252. else if(lRes != ERROR_SUCCESS)
  3253. return WBEM_E_FAILED;
  3254. }
  3255. m_pClassCache->InvalidateClass(wszClassName);
  3256. //
  3257. // Fire an event
  3258. //
  3259. hres = FireEvent(aEvents, WBEM_EVENTTYPE_ClassDeletion, wszClassName, pClass);
  3260. return S_OK;
  3261. }
  3262. CHR CNamespaceHandle::DeleteDerivedClasses(LPCWSTR wszClassName, CEventCollector &aEvents)
  3263. {
  3264. HRESULT hres;
  3265. CWStringArray wsChildHashes;
  3266. hres = GetChildHashes(wszClassName, wsChildHashes);
  3267. if(FAILED(hres))
  3268. return hres;
  3269. for(int i = 0; i < wsChildHashes.Size(); i++)
  3270. {
  3271. hres = DeleteClassByHash(wsChildHashes[i], aEvents);
  3272. if(FAILED(hres) && (hres != WBEM_E_NOT_FOUND))
  3273. {
  3274. return hres;
  3275. }
  3276. }
  3277. return S_OK;
  3278. }
  3279. CHR CNamespaceHandle::GetChildDefs(LPCWSTR wszClassName, bool bRecursive,
  3280. IWbemObjectSink* pSink, bool bClone)
  3281. {
  3282. CFileName wszHash;
  3283. if (wszHash == NULL)
  3284. return WBEM_E_OUT_OF_MEMORY;
  3285. if(!A51Hash(wszClassName, wszHash))
  3286. return WBEM_E_OUT_OF_MEMORY;
  3287. return GetChildDefsByHash(wszHash, bRecursive, pSink, bClone);
  3288. }
  3289. CHR CNamespaceHandle::GetChildDefsByHash(LPCWSTR wszHash, bool bRecursive,
  3290. IWbemObjectSink* pSink, bool bClone)
  3291. {
  3292. HRESULT hres;
  3293. long lStartIndex = m_pClassCache->GetLastInvalidationIndex();
  3294. //
  3295. // Get the hashes of the child filenames
  3296. //
  3297. CWStringArray wsChildHashes;
  3298. hres = GetChildHashesByHash(wszHash, wsChildHashes);
  3299. if(FAILED(hres))
  3300. return hres;
  3301. //
  3302. // Get their class definitions
  3303. //
  3304. for(int i = 0; i < wsChildHashes.Size(); i++)
  3305. {
  3306. LPCWSTR wszChildHash = wsChildHashes[i];
  3307. _IWmiObject* pClass = NULL;
  3308. hres = GetClassByHash(wszChildHash, bClone, &pClass, NULL, NULL, NULL);
  3309. if(FAILED(hres))
  3310. return hres;
  3311. CReleaseMe rm1(pClass);
  3312. hres = pSink->Indicate(1, (IWbemClassObject**)&pClass);
  3313. if(FAILED(hres))
  3314. return hres;
  3315. //
  3316. // Continue recursively if indicated
  3317. //
  3318. if(bRecursive)
  3319. {
  3320. hres = GetChildDefsByHash(wszChildHash, bRecursive, pSink, bClone);
  3321. if(FAILED(hres))
  3322. return hres;
  3323. }
  3324. }
  3325. //
  3326. // Mark cache completeness
  3327. //
  3328. m_pClassCache->DoneWithChildrenByHash(wszHash, bRecursive, lStartIndex);
  3329. return S_OK;
  3330. }
  3331. CHR CNamespaceHandle::GetChildHashes(LPCWSTR wszClassName,
  3332. CWStringArray& wsChildHashes)
  3333. {
  3334. CFileName wszHash;
  3335. if (wszHash == NULL)
  3336. return WBEM_E_OUT_OF_MEMORY;
  3337. if(!A51Hash(wszClassName, wszHash))
  3338. return WBEM_E_OUT_OF_MEMORY;
  3339. return GetChildHashesByHash(wszHash, wsChildHashes);
  3340. }
  3341. CHR CNamespaceHandle::GetChildHashesByHash(LPCWSTR wszHash,
  3342. CWStringArray& wsChildHashes)
  3343. {
  3344. HRESULT hres;
  3345. long lRes;
  3346. //Try retrieving the system classes namespace first...
  3347. if (g_pSystemClassNamespace && (wcscmp(m_wsNamespace, A51_SYSTEMCLASS_NS) != 0))
  3348. {
  3349. hres = g_pSystemClassNamespace->GetChildHashesByHash(wszHash, wsChildHashes);
  3350. if (FAILED(hres))
  3351. return hres;
  3352. }
  3353. //
  3354. // Construct the prefix for the children classes
  3355. //
  3356. CFileName wszChildPrefix;
  3357. if (wszChildPrefix == NULL)
  3358. return WBEM_E_OUT_OF_MEMORY;
  3359. hres = ConstructClassRelationshipsDirFromHash(wszHash, wszChildPrefix);
  3360. if(FAILED(hres))
  3361. return hres;
  3362. wcscat(wszChildPrefix, L"\\" A51_CHILDCLASS_FILE_PREFIX);
  3363. //
  3364. // Enumerate all such files in the cache
  3365. //
  3366. void* pHandle = NULL;
  3367. CFileName wszFileName;
  3368. if (wszFileName == NULL)
  3369. return WBEM_E_OUT_OF_MEMORY;
  3370. lRes = g_Glob.GetFileCache()->IndexEnumerationBegin(wszChildPrefix, &pHandle);
  3371. if (lRes == ERROR_FILE_NOT_FOUND)
  3372. return ERROR_SUCCESS;
  3373. else if (lRes != ERROR_SUCCESS)
  3374. return A51TranslateErrorCode(lRes);
  3375. while((lRes = g_Glob.GetFileCache()->IndexEnumerationNext(pHandle, wszFileName)) == ERROR_SUCCESS)
  3376. {
  3377. wsChildHashes.Add(wszFileName + wcslen(A51_CHILDCLASS_FILE_PREFIX));
  3378. }
  3379. g_Glob.GetFileCache()->IndexEnumerationEnd(pHandle);
  3380. if(lRes != ERROR_NO_MORE_FILES && lRes != S_OK)
  3381. return WBEM_E_FAILED;
  3382. else
  3383. return S_OK;
  3384. }
  3385. CHR CNamespaceHandle::ClassHasChildren(LPCWSTR wszClassName)
  3386. {
  3387. CFileName wszHash;
  3388. if (wszHash == NULL)
  3389. return WBEM_E_OUT_OF_MEMORY;
  3390. if(!A51Hash(wszClassName, wszHash))
  3391. return WBEM_E_OUT_OF_MEMORY;
  3392. HRESULT hres;
  3393. long lRes;
  3394. //Try retrieving the system classes namespace first...
  3395. if (g_pSystemClassNamespace && (wcscmp(m_wsNamespace, A51_SYSTEMCLASS_NS) != 0))
  3396. {
  3397. hres = g_pSystemClassNamespace->ClassHasChildren(wszClassName);
  3398. if (FAILED(hres) || (hres == WBEM_S_NO_ERROR))
  3399. return hres;
  3400. }
  3401. //
  3402. // Construct the prefix for the children classes
  3403. //
  3404. CFileName wszChildPrefix;
  3405. if (wszChildPrefix == NULL)
  3406. return WBEM_E_OUT_OF_MEMORY;
  3407. CFileName wszFileName;
  3408. if (wszFileName == NULL)
  3409. return WBEM_E_OUT_OF_MEMORY;
  3410. hres = ConstructClassRelationshipsDirFromHash(wszHash, wszChildPrefix);
  3411. if(FAILED(hres))
  3412. return hres;
  3413. wcscat(wszChildPrefix, L"\\" A51_CHILDCLASS_FILE_PREFIX);
  3414. void* pHandle = NULL;
  3415. lRes = g_Glob.GetFileCache()->IndexEnumerationBegin(wszChildPrefix, &pHandle);
  3416. if (lRes == ERROR_FILE_NOT_FOUND)
  3417. return WBEM_S_FALSE;
  3418. if (lRes != ERROR_SUCCESS)
  3419. return A51TranslateErrorCode(lRes);
  3420. g_Glob.GetFileCache()->IndexEnumerationEnd(pHandle);
  3421. return WBEM_S_NO_ERROR;
  3422. }
  3423. CHR CNamespaceHandle::ClassHasInstances(LPCWSTR wszClassName)
  3424. {
  3425. CFileName wszHash;
  3426. if (wszHash == NULL)
  3427. return WBEM_E_OUT_OF_MEMORY;
  3428. if(!A51Hash(wszClassName, wszHash))
  3429. return WBEM_E_OUT_OF_MEMORY;
  3430. return ClassHasInstancesFromClassHash(wszHash);
  3431. }
  3432. CHR CNamespaceHandle::ClassHasInstancesFromClassHash(LPCWSTR wszClassHash)
  3433. {
  3434. HRESULT hres;
  3435. long lRes;
  3436. //
  3437. // Check the instances in this namespace first. The instance directory in
  3438. // default scope is the class directory of the namespace
  3439. //
  3440. hres = ClassHasInstancesInScopeFromClassHash(m_wszClassRootDir,
  3441. wszClassHash);
  3442. if(hres != WBEM_S_FALSE)
  3443. return hres;
  3444. return WBEM_S_FALSE;
  3445. }
  3446. CHR CNamespaceHandle::ClassHasInstancesInScopeFromClassHash(
  3447. LPCWSTR wszInstanceRootDir, LPCWSTR wszClassHash)
  3448. {
  3449. CFileName wszFullDirName;
  3450. if (wszFullDirName == NULL)
  3451. return WBEM_E_OUT_OF_MEMORY;
  3452. wcscpy(wszFullDirName, wszInstanceRootDir);
  3453. wcscat(wszFullDirName, L"\\" A51_CLASSINST_DIR_PREFIX);
  3454. wcscat(wszFullDirName, wszClassHash);
  3455. wcscat(wszFullDirName, L"\\" A51_INSTLINK_FILE_PREFIX);
  3456. void* pHandle = NULL;
  3457. LONG lRes;
  3458. lRes = g_Glob.GetFileCache()->IndexEnumerationBegin(wszFullDirName, &pHandle);
  3459. if (lRes == ERROR_FILE_NOT_FOUND)
  3460. return WBEM_S_FALSE;
  3461. if (lRes != ERROR_SUCCESS)
  3462. {
  3463. return WBEM_E_FAILED;
  3464. }
  3465. if(pHandle)
  3466. g_Glob.GetFileCache()->IndexEnumerationEnd(pHandle);
  3467. return WBEM_S_NO_ERROR;
  3468. }
  3469. CHR CNamespaceHandle::EraseParentChildRelationship(
  3470. LPCWSTR wszChildFileName, LPCWSTR wszParentName)
  3471. {
  3472. CFileName wszParentChildFileName;
  3473. if (wszParentChildFileName == NULL)
  3474. return WBEM_E_OUT_OF_MEMORY;
  3475. HRESULT hres = ConstructParentChildFileName(wszChildFileName,
  3476. wszParentName,
  3477. wszParentChildFileName);
  3478. //
  3479. // Delete the file
  3480. //
  3481. long lRes = g_Glob.GetFileCache()->DeleteLink(wszParentChildFileName);
  3482. if(lRes != ERROR_SUCCESS)
  3483. return WBEM_E_FAILED;
  3484. return S_OK;
  3485. }
  3486. CHR CNamespaceHandle::EraseClassRelationships(LPCWSTR wszClassName,
  3487. _IWmiObject* pClass, LPCWSTR wszFileName)
  3488. {
  3489. HRESULT hres;
  3490. //
  3491. // Get the parent
  3492. //
  3493. VARIANT v;
  3494. VariantInit(&v);
  3495. hres = pClass->Get(L"__SUPERCLASS", 0, &v, NULL, NULL);
  3496. CClearMe cm(&v);
  3497. if(FAILED(hres))
  3498. return hres;
  3499. if(V_VT(&v) == VT_BSTR)
  3500. hres = EraseParentChildRelationship(wszFileName, V_BSTR(&v));
  3501. else
  3502. hres = EraseParentChildRelationship(wszFileName, L"");
  3503. if(FAILED(hres))
  3504. return hres;
  3505. //
  3506. // Erase references
  3507. //
  3508. hres = pClass->BeginEnumeration(WBEM_FLAG_REFS_ONLY);
  3509. if(FAILED(hres))
  3510. return hres;
  3511. BSTR strName = NULL;
  3512. while((hres = pClass->Next(0, &strName, NULL, NULL, NULL)) == S_OK)
  3513. {
  3514. CSysFreeMe sfm(strName);
  3515. hres = EraseClassReference(pClass, wszFileName, strName);
  3516. if(FAILED(hres) && (hres != WBEM_E_NOT_FOUND))
  3517. return hres;
  3518. }
  3519. pClass->EndEnumeration();
  3520. return S_OK;
  3521. }
  3522. CHR CNamespaceHandle::EraseClassReference(_IWmiObject* pReferringClass,
  3523. LPCWSTR wszReferringFile,
  3524. LPCWSTR wszReferringProp)
  3525. {
  3526. HRESULT hres;
  3527. //
  3528. // Figure out the class we are pointing to
  3529. //
  3530. DWORD dwSize = 0;
  3531. DWORD dwFlavor = 0;
  3532. CIMTYPE ct;
  3533. hres = pReferringClass->GetPropQual(wszReferringProp, L"CIMTYPE", 0, 0,
  3534. &ct, &dwFlavor, &dwSize, NULL);
  3535. if(dwSize == 0)
  3536. return WBEM_E_OUT_OF_MEMORY;
  3537. LPWSTR wszQual = (WCHAR*)TempAlloc(dwSize);
  3538. if(wszQual == NULL)
  3539. return WBEM_E_OUT_OF_MEMORY;
  3540. CTempFreeMe tfm(wszQual, dwSize);
  3541. hres = pReferringClass->GetPropQual(wszReferringProp, L"CIMTYPE", 0, dwSize,
  3542. &ct, &dwFlavor, &dwSize, wszQual);
  3543. if(FAILED(hres))
  3544. return hres;
  3545. //
  3546. // Parse out the class name
  3547. //
  3548. WCHAR* pwcColon = wcschr(wszQual, L':');
  3549. if(pwcColon == NULL)
  3550. return S_OK; // untyped reference requires no bookkeeping
  3551. LPCWSTR wszReferredToClass = pwcColon+1;
  3552. //
  3553. // Figure out the name of the file for the reference.
  3554. //
  3555. CFileName wszReferenceFile;
  3556. if (wszReferenceFile == NULL)
  3557. return WBEM_E_OUT_OF_MEMORY;
  3558. hres = ConstructClassReferenceFileName(wszReferredToClass,
  3559. wszReferringFile, wszReferringProp,
  3560. wszReferenceFile);
  3561. if(FAILED(hres))
  3562. return hres;
  3563. //
  3564. // Delete the file
  3565. //
  3566. long lRes = g_Glob.GetFileCache()->DeleteLink(wszReferenceFile);
  3567. if (lRes == ERROR_FILE_NOT_FOUND)
  3568. return WBEM_E_NOT_FOUND;
  3569. else if(lRes != ERROR_SUCCESS)
  3570. return WBEM_E_FAILED;
  3571. return S_OK;
  3572. }
  3573. CHR CNamespaceHandle::DeleteClassInstances(LPCWSTR wszClassName,
  3574. _IWmiObject* pClass,
  3575. CEventCollector &aEvents)
  3576. {
  3577. HRESULT hres;
  3578. //
  3579. // Find the link directory for this class
  3580. //
  3581. CFileName wszLinkDir;
  3582. if (wszLinkDir == NULL)
  3583. return WBEM_E_OUT_OF_MEMORY;
  3584. hres = ConstructLinkDirFromClass(wszLinkDir, wszClassName);
  3585. if(FAILED(hres))
  3586. return hres;
  3587. //
  3588. // Enumerate all links in it
  3589. //
  3590. CFileName wszSearchPrefix;
  3591. if (wszSearchPrefix == NULL)
  3592. return WBEM_E_OUT_OF_MEMORY;
  3593. wcscpy(wszSearchPrefix, wszLinkDir);
  3594. wcscat(wszSearchPrefix, L"\\" A51_INSTLINK_FILE_PREFIX);
  3595. //
  3596. // Prepare a buffer for instance definition file path
  3597. //
  3598. CFileName wszFullFileName;
  3599. if (wszFullFileName == NULL)
  3600. return WBEM_E_OUT_OF_MEMORY;
  3601. hres = ConstructKeyRootDirFromClass(wszFullFileName, wszClassName);
  3602. if(FAILED(hres))
  3603. {
  3604. if(hres == WBEM_E_CANNOT_BE_ABSTRACT)
  3605. return WBEM_S_NO_ERROR;
  3606. return hres;
  3607. }
  3608. long lDirLen = wcslen(wszFullFileName);
  3609. wszFullFileName[lDirLen] = L'\\';
  3610. lDirLen++;
  3611. CFileName wszFileName;
  3612. if (wszFullFileName == NULL)
  3613. return WBEM_E_OUT_OF_MEMORY;
  3614. void* hSearch;
  3615. long lRes = g_Glob.GetFileCache()->IndexEnumerationBegin(wszSearchPrefix, &hSearch);
  3616. if (lRes == ERROR_FILE_NOT_FOUND)
  3617. return ERROR_SUCCESS;
  3618. if (lRes != ERROR_SUCCESS)
  3619. return A51TranslateErrorCode(lRes);
  3620. while((lRes = g_Glob.GetFileCache()->IndexEnumerationNext(hSearch, wszFileName)) == ERROR_SUCCESS)
  3621. {
  3622. hres = ConstructInstDefNameFromLinkName(wszFullFileName+lDirLen, wszFileName);
  3623. if(FAILED(hres))
  3624. break;
  3625. _IWmiObject* pInst;
  3626. hres = FileToInstance(NULL, wszFullFileName, NULL, 0, &pInst);
  3627. if(FAILED(hres))
  3628. break;
  3629. CReleaseMe rm1(pInst);
  3630. //
  3631. // Delete the instance, knowing that we are deleting its class. That
  3632. // has an affect on how we deal with the references
  3633. //
  3634. hres = DeleteInstanceByFile(wszFullFileName, pInst, true, aEvents);
  3635. if(FAILED(hres))
  3636. break;
  3637. }
  3638. g_Glob.GetFileCache()->IndexEnumerationEnd(hSearch);
  3639. if (hres != ERROR_SUCCESS)
  3640. return hres;
  3641. if(lRes != ERROR_NO_MORE_FILES && lRes != S_OK)
  3642. {
  3643. return WBEM_E_FAILED;
  3644. }
  3645. return S_OK;
  3646. }
  3647. class CExecQueryObject : public CFiberTask
  3648. {
  3649. protected:
  3650. IWbemQuery* m_pQuery;
  3651. CDbIterator* m_pIter;
  3652. CNamespaceHandle* m_pNs;
  3653. DWORD m_lFlags;
  3654. public:
  3655. CExecQueryObject(CNamespaceHandle* pNs, IWbemQuery* pQuery,
  3656. CDbIterator* pIter, DWORD lFlags)
  3657. : m_pQuery(pQuery), m_pIter(pIter), m_pNs(pNs), m_lFlags(lFlags)
  3658. {
  3659. m_pQuery->AddRef();
  3660. m_pNs->AddRef();
  3661. //
  3662. // Does not AddRef the iterator --- iterator owns and cleans up the req
  3663. //
  3664. }
  3665. ~CExecQueryObject()
  3666. {
  3667. if(m_pQuery)
  3668. m_pQuery->Release();
  3669. if(m_pNs)
  3670. m_pNs->Release();
  3671. }
  3672. HRESULT Execute()
  3673. {
  3674. HRESULT hres = m_pNs->ExecQuerySink(m_pQuery, m_lFlags, 0, m_pIter, NULL);
  3675. m_pIter->SetStatus(WBEM_STATUS_COMPLETE, hres, NULL, NULL);
  3676. return hres;
  3677. }
  3678. };
  3679. CHR CNamespaceHandle::ExecQuery(
  3680. IWbemQuery *pQuery,
  3681. DWORD dwFlags,
  3682. DWORD dwRequestedHandleType,
  3683. DWORD *dwMessageFlags,
  3684. IWmiDbIterator **ppQueryResult
  3685. )
  3686. {
  3687. CDbIterator* pIter = new CDbIterator(m_pControl, m_bUseIteratorLock);
  3688. m_bUseIteratorLock = true;
  3689. if (pIter == NULL)
  3690. return WBEM_E_OUT_OF_MEMORY;
  3691. pIter->AddRef();
  3692. CReleaseMe rm1((IWmiDbIterator*)pIter);
  3693. //
  3694. // Create a fiber execution object
  3695. //
  3696. CExecQueryObject* pReq = new CExecQueryObject(this, pQuery, pIter, dwFlags);
  3697. if(pReq == NULL)
  3698. return WBEM_E_OUT_OF_MEMORY;
  3699. //
  3700. // Create a fiber for it
  3701. //
  3702. void* pFiber = CreateFiberForTask(pReq);
  3703. if(pFiber == NULL)
  3704. {
  3705. delete pReq;
  3706. return WBEM_E_OUT_OF_MEMORY;
  3707. }
  3708. pIter->SetExecFiber(pFiber, pReq);
  3709. return pIter->QueryInterface(IID_IWmiDbIterator, (void**)ppQueryResult);
  3710. }
  3711. CHR CNamespaceHandle::ExecQuerySink(
  3712. IWbemQuery *pQuery,
  3713. DWORD dwFlags,
  3714. DWORD dwRequestedHandleType,
  3715. IWbemObjectSink* pSink,
  3716. DWORD *dwMessageFlags
  3717. )
  3718. {
  3719. try
  3720. {
  3721. if (g_bShuttingDown)
  3722. return WBEM_E_SHUTTING_DOWN;
  3723. HRESULT hres;
  3724. LPWSTR wszQuery = NULL;
  3725. hres = pQuery->GetAnalysis(WMIQ_ANALYSIS_QUERY_TEXT, 0, (void**)&wszQuery);
  3726. if (FAILED(hres))
  3727. return hres;
  3728. DWORD dwLen = ((wcslen(wszQuery) + 1) * sizeof(wchar_t));
  3729. LPWSTR strParse = (LPWSTR)TempAlloc(dwLen);
  3730. if(strParse == NULL)
  3731. {
  3732. pQuery->FreeMemory(wszQuery);
  3733. return WBEM_E_OUT_OF_MEMORY;
  3734. }
  3735. CTempFreeMe tfm(strParse, dwLen);
  3736. wcscpy(strParse, wszQuery);
  3737. if(!_wcsicmp(wcstok(strParse, L" "), L"references"))
  3738. {
  3739. hres = ExecReferencesQuery(wszQuery, pSink);
  3740. pQuery->FreeMemory(wszQuery);
  3741. return hres;
  3742. }
  3743. QL_LEVEL_1_RPN_EXPRESSION* pExpr = NULL;
  3744. CTextLexSource Source(wszQuery);
  3745. QL1_Parser Parser(&Source);
  3746. int nRet = Parser.Parse(&pExpr);
  3747. CDeleteMe<QL_LEVEL_1_RPN_EXPRESSION> dm(pExpr);
  3748. pQuery->FreeMemory(wszQuery);
  3749. if (nRet == QL1_Parser::OUT_OF_MEMORY)
  3750. return WBEM_E_OUT_OF_MEMORY;
  3751. if (nRet != QL1_Parser::SUCCESS)
  3752. return WBEM_E_FAILED;
  3753. if(!_wcsicmp(pExpr->bsClassName, L"meta_class"))
  3754. {
  3755. return ExecClassQuery(pExpr, pSink, dwFlags);
  3756. }
  3757. else
  3758. {
  3759. return ExecInstanceQuery(pExpr, pExpr->bsClassName,
  3760. (dwFlags & WBEM_FLAG_SHALLOW ? false : true),
  3761. pSink);
  3762. }
  3763. }
  3764. catch (CX_MemoryException)
  3765. {
  3766. return WBEM_E_OUT_OF_MEMORY;
  3767. }
  3768. }
  3769. CHR CNamespaceHandle::ExecClassQuery(QL_LEVEL_1_RPN_EXPRESSION* pExpr,
  3770. IWbemObjectSink* pSink,
  3771. DWORD dwFlags)
  3772. {
  3773. if (g_bShuttingDown)
  3774. return WBEM_E_SHUTTING_DOWN;
  3775. HRESULT hres = ERROR_SUCCESS;
  3776. //
  3777. // Optimizations:
  3778. //
  3779. LPCWSTR wszClassName = NULL;
  3780. LPCWSTR wszSuperClass = NULL;
  3781. LPCWSTR wszAncestor = NULL;
  3782. bool bDontIncludeAncestorInResultSet = false;
  3783. if(pExpr->nNumTokens == 1)
  3784. {
  3785. QL_LEVEL_1_TOKEN* pToken = pExpr->pArrayOfTokens;
  3786. if(!_wcsicmp(pToken->PropertyName.GetStringAt(0), L"__SUPERCLASS") &&
  3787. pToken->nOperator == QL1_OPERATOR_EQUALS)
  3788. {
  3789. wszSuperClass = V_BSTR(&pToken->vConstValue);
  3790. }
  3791. else if(!_wcsicmp(pToken->PropertyName.GetStringAt(0), L"__THIS") &&
  3792. pToken->nOperator == QL1_OPERATOR_ISA)
  3793. {
  3794. wszAncestor = V_BSTR(&pToken->vConstValue);
  3795. }
  3796. else if(!_wcsicmp(pToken->PropertyName.GetStringAt(0), L"__CLASS") &&
  3797. pToken->nOperator == QL1_OPERATOR_EQUALS)
  3798. {
  3799. wszClassName = V_BSTR(&pToken->vConstValue);
  3800. }
  3801. }
  3802. else if (pExpr->nNumTokens == 3)
  3803. {
  3804. //
  3805. // This is a special optimisation used for deep enumeration of classes,
  3806. // and is expecting a query of:
  3807. // select * from meta_class where __this isa '<class_name>'
  3808. // and __class <> '<class_name>'
  3809. // where the <class_name> is the same class iin both cases. This will
  3810. // set the wszAncestor to <class_name> and propagate a flag to not
  3811. // include the actual ancestor in the list.
  3812. //
  3813. QL_LEVEL_1_TOKEN* pToken = pExpr->pArrayOfTokens;
  3814. if ((pToken[0].nTokenType == QL1_OP_EXPRESSION) &&
  3815. (pToken[1].nTokenType == QL1_OP_EXPRESSION) &&
  3816. (pToken[2].nTokenType == QL1_AND) &&
  3817. (pToken[0].nOperator == QL1_OPERATOR_ISA) &&
  3818. (pToken[1].nOperator == QL1_OPERATOR_NOTEQUALS) &&
  3819. (_wcsicmp(pToken[0].PropertyName.GetStringAt(0), L"__THIS") == 0) &&
  3820. (_wcsicmp(pToken[1].PropertyName.GetStringAt(0), L"__CLASS") == 0)
  3821. &&
  3822. (wcscmp(V_BSTR(&pToken[0].vConstValue),
  3823. V_BSTR(&pToken[1].vConstValue)) == 0)
  3824. )
  3825. {
  3826. wszAncestor = V_BSTR(&pToken[0].vConstValue);
  3827. bDontIncludeAncestorInResultSet = true;
  3828. }
  3829. }
  3830. if(wszClassName)
  3831. {
  3832. _IWmiObject* pClass = NULL;
  3833. hres = GetClassDirect(wszClassName, IID__IWmiObject, (void**)&pClass,
  3834. true, NULL, NULL, NULL);
  3835. if(hres == WBEM_E_NOT_FOUND)
  3836. {
  3837. //
  3838. // Class not there --- but that's success for us!
  3839. //
  3840. if (dwFlags & WBEM_FLAG_VALIDATE_CLASS_EXISTENCE)
  3841. return hres;
  3842. else
  3843. return S_OK;
  3844. }
  3845. else if(FAILED(hres))
  3846. {
  3847. return hres;
  3848. }
  3849. else
  3850. {
  3851. CReleaseMe rm1(pClass);
  3852. //
  3853. // Get the class
  3854. //
  3855. hres = pSink->Indicate(1, (IWbemClassObject**)&pClass);
  3856. if(FAILED(hres))
  3857. return hres;
  3858. return S_OK;
  3859. }
  3860. }
  3861. if (dwFlags & WBEM_FLAG_VALIDATE_CLASS_EXISTENCE)
  3862. {
  3863. _IWmiObject* pClass = NULL;
  3864. if (wszSuperClass)
  3865. hres = GetClassDirect(wszSuperClass, IID__IWmiObject, (void**)&pClass, false, NULL, NULL, NULL);
  3866. else if (wszAncestor)
  3867. hres = GetClassDirect(wszAncestor, IID__IWmiObject, (void**)&pClass, false, NULL, NULL, NULL);
  3868. if (FAILED(hres))
  3869. return hres;
  3870. if (pClass)
  3871. pClass->Release();
  3872. }
  3873. hres = EnumerateClasses(pSink, wszSuperClass, wszAncestor, true,
  3874. bDontIncludeAncestorInResultSet);
  3875. if(FAILED(hres))
  3876. return hres;
  3877. return S_OK;
  3878. }
  3879. CHR CNamespaceHandle::EnumerateClasses(IWbemObjectSink* pSink,
  3880. LPCWSTR wszSuperClass, LPCWSTR wszAncestor,
  3881. bool bClone,
  3882. bool bDontIncludeAncestorInResultSet)
  3883. {
  3884. if (g_bShuttingDown)
  3885. return WBEM_E_SHUTTING_DOWN;
  3886. CWStringArray wsClasses;
  3887. HRESULT hres;
  3888. //
  3889. // If superclass is given, check if its record is complete wrt children
  3890. //
  3891. if(wszSuperClass)
  3892. {
  3893. hres = m_pClassCache->EnumChildren(wszSuperClass, false, wsClasses);
  3894. if(hres == WBEM_S_FALSE)
  3895. {
  3896. //
  3897. // Not in cache --- get the info from files
  3898. //
  3899. return GetChildDefs(wszSuperClass, false, pSink, bClone);
  3900. }
  3901. else
  3902. {
  3903. if(FAILED(hres))
  3904. return hres;
  3905. return ListToEnum(wsClasses, pSink, bClone);
  3906. }
  3907. }
  3908. else
  3909. {
  3910. if(wszAncestor == NULL)
  3911. wszAncestor = L"";
  3912. hres = m_pClassCache->EnumChildren(wszAncestor, true, wsClasses);
  3913. if(hres == WBEM_S_FALSE)
  3914. {
  3915. //
  3916. // Not in cache --- get the info from files
  3917. //
  3918. hres = GetChildDefs(wszAncestor, true, pSink, bClone);
  3919. if(FAILED(hres))
  3920. return hres;
  3921. if(*wszAncestor && !bDontIncludeAncestorInResultSet)
  3922. {
  3923. //
  3924. // The class is derived from itself
  3925. //
  3926. _IWmiObject* pClass = NULL;
  3927. hres = GetClassDirect(wszAncestor, IID__IWmiObject,
  3928. (void**)&pClass, bClone, NULL, NULL, NULL);
  3929. if(FAILED(hres))
  3930. return hres;
  3931. CReleaseMe rm1(pClass);
  3932. hres = pSink->Indicate(1, (IWbemClassObject**)&pClass);
  3933. if(FAILED(hres))
  3934. return hres;
  3935. }
  3936. return S_OK;
  3937. }
  3938. else
  3939. {
  3940. if(FAILED(hres))
  3941. return hres;
  3942. if(*wszAncestor && !bDontIncludeAncestorInResultSet)
  3943. {
  3944. wsClasses.Add(wszAncestor);
  3945. }
  3946. return ListToEnum(wsClasses, pSink, bClone);
  3947. }
  3948. }
  3949. }
  3950. CHR CNamespaceHandle::ListToEnum(CWStringArray& wsClasses,
  3951. IWbemObjectSink* pSink, bool bClone)
  3952. {
  3953. HRESULT hres;
  3954. for(int i = 0; i < wsClasses.Size(); i++)
  3955. {
  3956. _IWmiObject* pClass = NULL;
  3957. if(wsClasses[i] == NULL || wsClasses[i][0] == 0)
  3958. continue;
  3959. hres = GetClassDirect(wsClasses[i], IID__IWmiObject, (void**)&pClass,
  3960. bClone, NULL, NULL, NULL);
  3961. if(FAILED(hres))
  3962. {
  3963. if(hres == WBEM_E_NOT_FOUND)
  3964. {
  3965. // That's OK --- class got removed
  3966. }
  3967. else
  3968. return hres;
  3969. }
  3970. else
  3971. {
  3972. CReleaseMe rm1(pClass);
  3973. hres = pSink->Indicate(1, (IWbemClassObject**)&pClass);
  3974. if(FAILED(hres))
  3975. return hres;
  3976. }
  3977. }
  3978. return WBEM_S_NO_ERROR;
  3979. }
  3980. CHR CNamespaceHandle::ExecInstanceQuery(QL_LEVEL_1_RPN_EXPRESSION* pQuery,
  3981. LPCWSTR wszClassName, bool bDeep,
  3982. IWbemObjectSink* pSink)
  3983. {
  3984. if (g_bShuttingDown)
  3985. return WBEM_E_SHUTTING_DOWN;
  3986. HRESULT hres;
  3987. WCHAR wszHash[MAX_HASH_LEN+1];
  3988. if(!Hash(wszClassName, wszHash))
  3989. return WBEM_E_OUT_OF_MEMORY;
  3990. if(bDeep)
  3991. hres = ExecDeepInstanceQuery(pQuery, wszHash, pSink);
  3992. else
  3993. hres = ExecShallowInstanceQuery(pQuery, wszHash, pSink);
  3994. if(FAILED(hres))
  3995. return hres;
  3996. return S_OK;
  3997. }
  3998. CHR CNamespaceHandle::ExecDeepInstanceQuery(
  3999. QL_LEVEL_1_RPN_EXPRESSION* pQuery,
  4000. LPCWSTR wszClassHash,
  4001. IWbemObjectSink* pSink)
  4002. {
  4003. if (g_bShuttingDown)
  4004. return WBEM_E_SHUTTING_DOWN;
  4005. HRESULT hres;
  4006. //
  4007. // Get all our instances
  4008. //
  4009. hres = ExecShallowInstanceQuery(pQuery, wszClassHash, pSink);
  4010. if(FAILED(hres))
  4011. return hres;
  4012. CWStringArray awsChildHashes;
  4013. //
  4014. // Check if the list of child classes is known to the cache
  4015. //
  4016. hres = m_pClassCache->EnumChildKeysByKey(wszClassHash, awsChildHashes);
  4017. if (hres == WBEM_S_FALSE)
  4018. {
  4019. //
  4020. // OK --- get them from the disk
  4021. //
  4022. hres = GetChildHashesByHash(wszClassHash, awsChildHashes);
  4023. }
  4024. if (FAILED(hres))
  4025. {
  4026. return hres;
  4027. }
  4028. //
  4029. // We have our hashes --- call them recursively
  4030. //
  4031. for(int i = 0; i < awsChildHashes.Size(); i++)
  4032. {
  4033. LPCWSTR wszChildHash = awsChildHashes[i];
  4034. hres = ExecDeepInstanceQuery(pQuery, wszChildHash, pSink);
  4035. if(FAILED(hres))
  4036. return hres;
  4037. }
  4038. return S_OK;
  4039. }
  4040. CHR CNamespaceHandle::ExecShallowInstanceQuery(
  4041. QL_LEVEL_1_RPN_EXPRESSION* pQuery,
  4042. LPCWSTR wszClassHash,
  4043. IWbemObjectSink* pSink)
  4044. {
  4045. if (g_bShuttingDown)
  4046. return WBEM_E_SHUTTING_DOWN;
  4047. HRESULT hres;
  4048. //
  4049. // Enumerate all files in the link directory
  4050. //
  4051. CFileName wszSearchPrefix;
  4052. if (wszSearchPrefix == NULL)
  4053. return WBEM_E_OUT_OF_MEMORY;
  4054. hres = ConstructLinkDirFromClassHash(wszSearchPrefix, wszClassHash);
  4055. if(FAILED(hres))
  4056. return hres;
  4057. wcscat(wszSearchPrefix, L"\\" A51_INSTLINK_FILE_PREFIX);
  4058. //
  4059. // Get Class definition
  4060. //
  4061. _IWmiObject* pClass = NULL;
  4062. hres = GetClassByHash(wszClassHash, false, &pClass, NULL, NULL, NULL);
  4063. if(FAILED(hres))
  4064. return hres;
  4065. CReleaseMe rm1(pClass);
  4066. CFileName fn;
  4067. if (fn == NULL)
  4068. return WBEM_E_OUT_OF_MEMORY;
  4069. void* hSearch;
  4070. long lRes = g_Glob.GetFileCache()->ObjectEnumerationBegin(wszSearchPrefix, &hSearch);
  4071. if (lRes == ERROR_FILE_NOT_FOUND)
  4072. return S_OK;
  4073. else if (lRes != ERROR_SUCCESS)
  4074. return A51TranslateErrorCode(lRes);
  4075. BYTE *pBlob = NULL;
  4076. DWORD dwSize = 0;
  4077. while ((hres == ERROR_SUCCESS) &&
  4078. (lRes = g_Glob.GetFileCache()->ObjectEnumerationNext(hSearch, fn, &pBlob, &dwSize) == ERROR_SUCCESS))
  4079. {
  4080. _IWmiObject* pInstance = NULL;
  4081. hres = FileToInstance(pClass, fn, pBlob, dwSize, &pInstance, true);
  4082. CReleaseMe rm2(pInstance);
  4083. if (SUCCEEDED(hres))
  4084. hres = pSink->Indicate(1, (IWbemClassObject**)&pInstance);
  4085. g_Glob.GetFileCache()->ObjectEnumerationFree(hSearch, pBlob);
  4086. }
  4087. g_Glob.GetFileCache()->ObjectEnumerationEnd(hSearch);
  4088. if (lRes == ERROR_NO_MORE_FILES)
  4089. return S_OK;
  4090. else if (lRes)
  4091. return A51TranslateErrorCode(lRes);
  4092. else
  4093. return hres;
  4094. }
  4095. CHR CNamespaceHandle::ExecReferencesQuery(LPCWSTR wszQuery,
  4096. IWbemObjectSink* pSink)
  4097. {
  4098. if (g_bShuttingDown)
  4099. return WBEM_E_SHUTTING_DOWN;
  4100. HRESULT hres;
  4101. //
  4102. // Make a copy for parsing
  4103. //
  4104. LPWSTR wszParse = new WCHAR[wcslen(wszQuery)+1];
  4105. if (wszParse == NULL)
  4106. return WBEM_E_OUT_OF_MEMORY;
  4107. CVectorDeleteMe<WCHAR> vdm(wszParse);
  4108. wcscpy(wszParse, wszQuery);
  4109. //
  4110. // Extract the path of the target object.
  4111. //
  4112. //
  4113. // Find the first brace
  4114. //
  4115. WCHAR* pwcStart = wcschr(wszParse, L'{');
  4116. if(pwcStart == NULL)
  4117. return WBEM_E_INVALID_QUERY;
  4118. //
  4119. // Find the beginning of the path
  4120. //
  4121. while(*pwcStart && iswspace(*pwcStart)) pwcStart++;
  4122. if(!*pwcStart)
  4123. return WBEM_E_INVALID_QUERY;
  4124. pwcStart++;
  4125. //
  4126. // Find the ending curly brace
  4127. //
  4128. WCHAR* pwc = pwcStart;
  4129. WCHAR wcCurrentQuote = 0;
  4130. while(*pwc && (wcCurrentQuote || *pwc != L'}'))
  4131. {
  4132. if(wcCurrentQuote)
  4133. {
  4134. if(*pwc == L'\\')
  4135. {
  4136. pwc++;
  4137. }
  4138. else if(*pwc == wcCurrentQuote)
  4139. wcCurrentQuote = 0;
  4140. }
  4141. else if(*pwc == L'\'' || *pwc == L'"')
  4142. wcCurrentQuote = *pwc;
  4143. pwc++;
  4144. }
  4145. if(*pwc != L'}')
  4146. return WBEM_E_INVALID_QUERY;
  4147. //
  4148. // Find the end of the path
  4149. //
  4150. WCHAR* pwcEnd = pwc-1;
  4151. while(iswspace(*pwcEnd)) pwcEnd--;
  4152. pwcEnd[1] = 0;
  4153. LPWSTR wszTargetPath = pwcStart;
  4154. if(wszTargetPath == NULL)
  4155. return WBEM_E_INVALID_QUERY;
  4156. //
  4157. // Parse the path
  4158. //
  4159. DWORD dwLen = (wcslen(wszTargetPath)+1) * sizeof(WCHAR);
  4160. LPWSTR wszKey = (LPWSTR)TempAlloc(dwLen);
  4161. if(wszKey == NULL)
  4162. return WBEM_E_OUT_OF_MEMORY;
  4163. CTempFreeMe tfm(wszKey, dwLen);
  4164. LPWSTR wszClassName = NULL;
  4165. bool bIsClass;
  4166. hres = ComputeKeyFromPath(wszTargetPath, wszKey, &wszClassName, &bIsClass);
  4167. if(FAILED(hres))
  4168. return hres;
  4169. CTempFreeMe tfm1(wszClassName, (wcslen(wszClassName)+1) * sizeof(WCHAR*));
  4170. if(bIsClass)
  4171. {
  4172. //
  4173. // Need to execute an instance reference query to find all instances
  4174. // pointing to this class
  4175. //
  4176. hres = ExecInstanceRefQuery(wszQuery, NULL, wszClassName, pSink);
  4177. if(FAILED(hres))
  4178. return hres;
  4179. hres = ExecClassRefQuery(wszQuery, wszClassName, pSink);
  4180. if(FAILED(hres))
  4181. return hres;
  4182. }
  4183. else
  4184. {
  4185. hres = ExecInstanceRefQuery(wszQuery, wszClassName, wszKey, pSink);
  4186. if(FAILED(hres))
  4187. return hres;
  4188. }
  4189. return S_OK;
  4190. }
  4191. CHR CNamespaceHandle::ExecInstanceRefQuery(LPCWSTR wszQuery,
  4192. LPCWSTR wszClassName,
  4193. LPCWSTR wszKey,
  4194. IWbemObjectSink* pSink)
  4195. {
  4196. if (g_bShuttingDown)
  4197. return WBEM_E_SHUTTING_DOWN;
  4198. HRESULT hres;
  4199. //
  4200. // Find the instance's ref dir.
  4201. //
  4202. CFileName wszReferenceDir;
  4203. if (wszReferenceDir == NULL)
  4204. return WBEM_E_OUT_OF_MEMORY;
  4205. hres = ConstructReferenceDirFromKey(wszClassName, wszKey, wszReferenceDir);
  4206. if(FAILED(hres))
  4207. return hres;
  4208. CFileName wszReferenceMask;
  4209. if (wszReferenceMask == NULL)
  4210. return WBEM_E_OUT_OF_MEMORY;
  4211. wcscpy(wszReferenceMask, wszReferenceDir);
  4212. wcscat(wszReferenceMask, L"\\" A51_REF_FILE_PREFIX);
  4213. //
  4214. // Prepare a buffer for file path
  4215. //
  4216. CFileName wszFullFileName;
  4217. if (wszFullFileName == NULL)
  4218. return WBEM_E_OUT_OF_MEMORY;
  4219. wcscpy(wszFullFileName, wszReferenceDir);
  4220. wcscat(wszFullFileName, L"\\");
  4221. long lDirLen = wcslen(wszFullFileName);
  4222. HRESULT hresGlobal = WBEM_S_NO_ERROR;
  4223. CFileName wszReferrerFileName;
  4224. if (wszReferrerFileName == NULL)
  4225. return WBEM_E_OUT_OF_MEMORY;
  4226. wcscpy(wszReferrerFileName, g_Glob.GetRootDir());
  4227. CFileName wszFileName;
  4228. if (wszFileName == NULL)
  4229. return WBEM_E_OUT_OF_MEMORY;
  4230. //
  4231. // Enumerate all files in it
  4232. //
  4233. void* hSearch;
  4234. long lRes = g_Glob.GetFileCache()->IndexEnumerationBegin(wszReferenceMask, &hSearch);
  4235. if (lRes == ERROR_FILE_NOT_FOUND)
  4236. return S_OK;
  4237. else if (lRes != ERROR_SUCCESS)
  4238. return A51TranslateErrorCode(lRes);
  4239. while((lRes = g_Glob.GetFileCache()->IndexEnumerationNext(hSearch, wszFileName)) == ERROR_SUCCESS)
  4240. {
  4241. wcscpy(wszFullFileName+lDirLen, wszFileName);
  4242. LPWSTR wszReferrerClass = NULL;
  4243. LPWSTR wszReferrerProp = NULL;
  4244. LPWSTR wszReferrerNamespace = NULL;
  4245. hres = GetReferrerFromFile(wszFullFileName, wszReferrerFileName + g_Glob.GetRootDirLen(), &wszReferrerNamespace, &wszReferrerClass, &wszReferrerProp);
  4246. if(FAILED(hres))
  4247. continue;
  4248. CVectorDeleteMe<WCHAR> vdm1(wszReferrerClass);
  4249. CVectorDeleteMe<WCHAR> vdm2(wszReferrerProp);
  4250. CVectorDeleteMe<WCHAR> vdm3(wszReferrerNamespace);
  4251. // Check if the namespace of the referring object is the same as ours
  4252. CNamespaceHandle* pReferrerHandle = NULL;
  4253. if(wbem_wcsicmp(wszReferrerNamespace, m_wsNamespace))
  4254. {
  4255. // Open the other namespace
  4256. hres = m_pRepository->GetNamespaceHandle(wszReferrerNamespace, &pReferrerHandle);
  4257. if(FAILED(hres))
  4258. {
  4259. ERRORTRACE((LOG_WBEMCORE, "Unable to open referring namespace '%S' in namespace '%S'\n", wszReferrerNamespace, (LPCWSTR)m_wsNamespace));
  4260. hresGlobal = hres;
  4261. continue;
  4262. }
  4263. }
  4264. else
  4265. {
  4266. pReferrerHandle = this;
  4267. pReferrerHandle->AddRef();
  4268. }
  4269. CReleaseMe rm1(pReferrerHandle);
  4270. _IWmiObject* pInstance = NULL;
  4271. hres = pReferrerHandle->FileToInstance(NULL, wszReferrerFileName, NULL, 0, &pInstance);
  4272. if(FAILED(hres))
  4273. {
  4274. // Oh well --- continue;
  4275. hresGlobal = hres;
  4276. }
  4277. else
  4278. {
  4279. CReleaseMe rm2(pInstance);
  4280. hres = pSink->Indicate(1, (IWbemClassObject**)&pInstance);
  4281. if(FAILED(hres))
  4282. {
  4283. hresGlobal = hres;
  4284. break;
  4285. }
  4286. }
  4287. }
  4288. g_Glob.GetFileCache()->IndexEnumerationEnd(hSearch);
  4289. if (hresGlobal != ERROR_SUCCESS)
  4290. return hresGlobal;
  4291. if(lRes == ERROR_NO_MORE_FILES)
  4292. {
  4293. //
  4294. // No files in dir --- no problem
  4295. //
  4296. return WBEM_S_NO_ERROR;
  4297. }
  4298. else if(lRes != ERROR_SUCCESS)
  4299. {
  4300. return WBEM_E_FAILED;
  4301. }
  4302. return WBEM_S_NO_ERROR;
  4303. }
  4304. CHR CNamespaceHandle::GetReferrerFromFile(LPCWSTR wszReferenceFile,
  4305. LPWSTR wszReferrerRelFile,
  4306. LPWSTR* pwszReferrerNamespace,
  4307. LPWSTR* pwszReferrerClass,
  4308. LPWSTR* pwszReferrerProp)
  4309. {
  4310. //
  4311. // Get the entire buffer from the file
  4312. //
  4313. BYTE* pBuffer = NULL;
  4314. DWORD dwBufferLen = 0;
  4315. long lRes = g_Glob.GetFileCache()->ReadObject(wszReferenceFile, &dwBufferLen,
  4316. &pBuffer);
  4317. if(lRes != ERROR_SUCCESS)
  4318. return WBEM_E_FAILED;
  4319. CTempFreeMe tfm(pBuffer, dwBufferLen);
  4320. if(dwBufferLen == 0)
  4321. return WBEM_E_OUT_OF_MEMORY;
  4322. BYTE* pCurrent = pBuffer;
  4323. DWORD dwStringLen;
  4324. //
  4325. // Get the referrer namespace
  4326. //
  4327. memcpy(&dwStringLen, pCurrent, sizeof(DWORD));
  4328. pCurrent += sizeof(DWORD);
  4329. *pwszReferrerNamespace = new WCHAR[dwStringLen+1];
  4330. if (*pwszReferrerNamespace == NULL)
  4331. return WBEM_E_OUT_OF_MEMORY;
  4332. (*pwszReferrerNamespace)[dwStringLen] = 0;
  4333. memcpy(*pwszReferrerNamespace, pCurrent, dwStringLen*sizeof(WCHAR));
  4334. pCurrent += sizeof(WCHAR)*dwStringLen;
  4335. //
  4336. // Get the referrer class name
  4337. //
  4338. memcpy(&dwStringLen, pCurrent, sizeof(DWORD));
  4339. pCurrent += sizeof(DWORD);
  4340. *pwszReferrerClass = new WCHAR[dwStringLen+1];
  4341. if (*pwszReferrerClass == NULL)
  4342. return WBEM_E_OUT_OF_MEMORY;
  4343. (*pwszReferrerClass)[dwStringLen] = 0;
  4344. memcpy(*pwszReferrerClass, pCurrent, dwStringLen*sizeof(WCHAR));
  4345. pCurrent += sizeof(WCHAR)*dwStringLen;
  4346. //
  4347. // Get the referrer property
  4348. //
  4349. memcpy(&dwStringLen, pCurrent, sizeof(DWORD));
  4350. pCurrent += sizeof(DWORD);
  4351. *pwszReferrerProp = new WCHAR[dwStringLen+1];
  4352. if (*pwszReferrerProp == NULL)
  4353. return WBEM_E_OUT_OF_MEMORY;
  4354. (*pwszReferrerProp)[dwStringLen] = 0;
  4355. memcpy(*pwszReferrerProp, pCurrent, dwStringLen*sizeof(WCHAR));
  4356. pCurrent += sizeof(WCHAR)*dwStringLen;
  4357. //
  4358. // Get referrer file path
  4359. //
  4360. memcpy(&dwStringLen, pCurrent, sizeof(DWORD));
  4361. pCurrent += sizeof(DWORD);
  4362. wszReferrerRelFile[dwStringLen] = 0;
  4363. memcpy(wszReferrerRelFile, pCurrent, dwStringLen*sizeof(WCHAR));
  4364. pCurrent += sizeof(WCHAR)*dwStringLen;
  4365. return S_OK;
  4366. }
  4367. CHR CNamespaceHandle::ExecClassRefQuery(LPCWSTR wszQuery,
  4368. LPCWSTR wszClassName,
  4369. IWbemObjectSink* pSink)
  4370. {
  4371. if (g_bShuttingDown)
  4372. return WBEM_E_SHUTTING_DOWN;
  4373. HRESULT hres = ERROR_SUCCESS;
  4374. //Execute against system class namespace first
  4375. if (g_pSystemClassNamespace && (wcscmp(m_wsNamespace, A51_SYSTEMCLASS_NS) != 0))
  4376. {
  4377. hres = g_pSystemClassNamespace->ExecClassRefQuery(wszQuery, wszClassName, pSink);
  4378. if (FAILED(hres))
  4379. return hres;
  4380. }
  4381. //
  4382. // Find the class's ref dir.
  4383. //
  4384. CFileName wszReferenceDir;
  4385. if (wszReferenceDir == NULL)
  4386. return WBEM_E_OUT_OF_MEMORY;
  4387. hres = ConstructClassRelationshipsDir(wszClassName, wszReferenceDir);
  4388. CFileName wszReferenceMask;
  4389. if (wszReferenceMask == NULL)
  4390. return WBEM_E_OUT_OF_MEMORY;
  4391. wcscpy(wszReferenceMask, wszReferenceDir);
  4392. wcscat(wszReferenceMask, L"\\" A51_REF_FILE_PREFIX);
  4393. CFileName wszFileName;
  4394. if (wszFileName == NULL)
  4395. return WBEM_E_OUT_OF_MEMORY;
  4396. //
  4397. // Enumerate all files in it
  4398. //
  4399. void* hSearch;
  4400. long lRes = g_Glob.GetFileCache()->IndexEnumerationBegin(wszReferenceMask, &hSearch);
  4401. if (lRes == ERROR_FILE_NOT_FOUND)
  4402. return S_OK;
  4403. else if (lRes != ERROR_SUCCESS)
  4404. return A51TranslateErrorCode(lRes);
  4405. while ((hres == ERROR_SUCCESS) && ((lRes = g_Glob.GetFileCache()->IndexEnumerationNext(hSearch, wszFileName) == ERROR_SUCCESS)))
  4406. {
  4407. //
  4408. // Extract the class hash from the name of the file
  4409. //
  4410. LPCWSTR wszReferrerHash = wszFileName + wcslen(A51_REF_FILE_PREFIX);
  4411. //
  4412. // Get the class from that hash
  4413. //
  4414. _IWmiObject* pClass = NULL;
  4415. hres = GetClassByHash(wszReferrerHash, true, &pClass, NULL, NULL, NULL);
  4416. if(hres == WBEM_E_NOT_FOUND)
  4417. {
  4418. hres = ERROR_SUCCESS;
  4419. continue;
  4420. }
  4421. CReleaseMe rm1(pClass);
  4422. if (hres == ERROR_SUCCESS)
  4423. hres = pSink->Indicate(1, (IWbemClassObject**)&pClass);
  4424. }
  4425. g_Glob.GetFileCache()->IndexEnumerationEnd(hSearch);
  4426. if (hres != ERROR_SUCCESS)
  4427. return hres;
  4428. if(lRes == ERROR_NO_MORE_FILES)
  4429. {
  4430. //
  4431. // No files in dir --- no problem
  4432. //
  4433. return WBEM_S_NO_ERROR;
  4434. }
  4435. else if(lRes != ERROR_SUCCESS)
  4436. {
  4437. return WBEM_E_FAILED;
  4438. }
  4439. return S_OK;
  4440. }
  4441. bool CNamespaceHandle::Hash(LPCWSTR wszName, LPWSTR wszHash)
  4442. {
  4443. return A51Hash(wszName, wszHash);
  4444. }
  4445. CHR CNamespaceHandle::InstanceToFile(IWbemClassObject* pInst,
  4446. LPCWSTR wszClassName, LPCWSTR wszFileName1, LPCWSTR wszFileName2,
  4447. __int64 nClassTime)
  4448. {
  4449. HRESULT hres;
  4450. //
  4451. // Allocate enough space for the buffer
  4452. //
  4453. _IWmiObject* pInstEx;
  4454. pInst->QueryInterface(IID__IWmiObject, (void**)&pInstEx);
  4455. CReleaseMe rm1(pInstEx);
  4456. DWORD dwInstancePartLen = 0;
  4457. hres = pInstEx->Unmerge(0, 0, &dwInstancePartLen, NULL);
  4458. //
  4459. // Add enough room for the class hash
  4460. //
  4461. DWORD dwClassHashLen = MAX_HASH_LEN * sizeof(WCHAR);
  4462. DWORD dwTotalLen = dwInstancePartLen + dwClassHashLen + sizeof(__int64)*2;
  4463. BYTE* pBuffer = (BYTE*)TempAlloc(dwTotalLen);
  4464. if (pBuffer == NULL)
  4465. return WBEM_E_OUT_OF_MEMORY;
  4466. CTempFreeMe vdm(pBuffer, dwTotalLen);
  4467. //
  4468. // Write the class hash
  4469. //
  4470. if(!Hash(wszClassName, (LPWSTR)pBuffer))
  4471. return WBEM_E_OUT_OF_MEMORY;
  4472. memcpy(pBuffer + dwClassHashLen, &g_nCurrentTime, sizeof(__int64));
  4473. g_nCurrentTime++;
  4474. memcpy(pBuffer + dwClassHashLen + sizeof(__int64), &nClassTime,
  4475. sizeof(__int64));
  4476. //
  4477. // Unmerge the instance into a buffer
  4478. //
  4479. DWORD dwLen;
  4480. hres = pInstEx->Unmerge(0, dwInstancePartLen, &dwLen,
  4481. pBuffer + dwClassHashLen + sizeof(__int64)*2);
  4482. if(FAILED(hres))
  4483. return hres;
  4484. //
  4485. // Write to the file only as much as we have actually used!
  4486. //
  4487. long lRes = g_Glob.GetFileCache()->WriteObject(wszFileName1, wszFileName2,
  4488. dwClassHashLen + sizeof(__int64)*2 + dwLen, pBuffer);
  4489. if(lRes != ERROR_SUCCESS)
  4490. return WBEM_E_FAILED;
  4491. return WBEM_S_NO_ERROR;
  4492. }
  4493. CHR CNamespaceHandle::ClassToFile(_IWmiObject* pParentClass,
  4494. _IWmiObject* pClass, LPCWSTR wszFileName,
  4495. __int64 nFakeUpdateTime)
  4496. {
  4497. HRESULT hres;
  4498. //
  4499. // Get superclass name
  4500. //
  4501. VARIANT vSuper;
  4502. hres = pClass->Get(L"__SUPERCLASS", 0, &vSuper, NULL, NULL);
  4503. if(FAILED(hres))
  4504. return hres;
  4505. CClearMe cm1(&vSuper);
  4506. LPCWSTR wszSuper;
  4507. if(V_VT(&vSuper) == VT_BSTR)
  4508. wszSuper = V_BSTR(&vSuper);
  4509. else
  4510. wszSuper = L"";
  4511. VARIANT vClassName;
  4512. hres = pClass->Get(L"__CLASS", 0, &vClassName, NULL, NULL);
  4513. if(FAILED(hres))
  4514. return hres;
  4515. CClearMe cm2(&vClassName);
  4516. LPCWSTR wszClassName;
  4517. if(V_VT(&vClassName) == VT_BSTR)
  4518. wszClassName = V_BSTR(&vClassName);
  4519. else
  4520. wszClassName = L"";
  4521. #ifdef A51_SUPER_VALIDATION
  4522. if (wcscmp(wszSuper, wszClassName) == 0)
  4523. {
  4524. OutputDebugString(L"WinMgmt: Repository is trying to put a class that is derived from itself!\n");
  4525. DebugBreak();
  4526. return WBEM_E_FAILED;
  4527. }
  4528. if (pClass->IsObjectInstance() == S_OK)
  4529. {
  4530. OutputDebugString(L"WinMgmt: Repository is trying to store an instance in a class blob!\n");
  4531. DebugBreak();
  4532. return WBEM_E_FAILED;
  4533. }
  4534. if (FAILED(pClass->ValidateObject(WMIOBJECT_VALIDATEOBJECT_FLAG_FORCE)))
  4535. {
  4536. OutputDebugString(L"WinMgmt: Repository was gived an invalid class to store in the repository!\n");
  4537. DebugBreak();
  4538. return WBEM_E_FAILED;
  4539. }
  4540. #endif
  4541. //
  4542. // Get unmerge length
  4543. //
  4544. DWORD dwUnmergedLen = 0;
  4545. hres = pClass->Unmerge(0, 0, &dwUnmergedLen, NULL);
  4546. //
  4547. // Add enough space for the parent class name and the timestamp
  4548. //
  4549. DWORD dwSuperLen = sizeof(DWORD) + wcslen(wszSuper)*sizeof(WCHAR);
  4550. DWORD dwLen = dwUnmergedLen + dwSuperLen + sizeof(__int64);
  4551. BYTE* pBuffer = (BYTE*)TempAlloc(dwLen);
  4552. if (pBuffer == NULL)
  4553. return WBEM_E_OUT_OF_MEMORY;
  4554. CTempFreeMe vdm(pBuffer, dwLen);
  4555. //
  4556. // Write superclass name
  4557. //
  4558. DWORD dwActualSuperLen = wcslen(wszSuper);
  4559. memcpy(pBuffer, &dwActualSuperLen, sizeof(DWORD));
  4560. memcpy(pBuffer + sizeof(DWORD), wszSuper, wcslen(wszSuper)*sizeof(WCHAR));
  4561. //
  4562. // Write the timestamp
  4563. //
  4564. if(nFakeUpdateTime == 0)
  4565. {
  4566. nFakeUpdateTime = g_nCurrentTime;
  4567. g_nCurrentTime++;
  4568. }
  4569. memcpy(pBuffer + dwSuperLen, &nFakeUpdateTime, sizeof(__int64));
  4570. //
  4571. // Write the unmerged portion
  4572. //
  4573. BYTE* pUnmergedPortion = pBuffer + dwSuperLen + sizeof(__int64);
  4574. hres = pClass->Unmerge(0, dwUnmergedLen, &dwUnmergedLen,
  4575. pUnmergedPortion);
  4576. if(FAILED(hres))
  4577. return hres;
  4578. //
  4579. // Stash away the real length
  4580. //
  4581. DWORD dwFileLen = dwUnmergedLen + dwSuperLen + sizeof(__int64);
  4582. long lRes = g_Glob.GetFileCache()->WriteObject(wszFileName, NULL, dwFileLen, pBuffer);
  4583. if(lRes != ERROR_SUCCESS)
  4584. return WBEM_E_FAILED;
  4585. //
  4586. // To properly cache the new class definition, first invalidate it
  4587. //
  4588. hres = m_pClassCache->InvalidateClass(wszClassName);
  4589. if(FAILED(hres))
  4590. return hres;
  4591. //
  4592. // Now, remerge the unmerged portion back in
  4593. //
  4594. if(pParentClass == NULL)
  4595. {
  4596. //
  4597. // Get the empty class
  4598. //
  4599. hres = GetClassDirect(NULL, IID__IWmiObject, (void**)&pParentClass,
  4600. false, NULL, NULL, NULL);
  4601. if(FAILED(hres))
  4602. return hres;
  4603. }
  4604. else
  4605. pParentClass->AddRef();
  4606. CReleaseMe rm0(pParentClass);
  4607. _IWmiObject* pNewObj;
  4608. hres = pParentClass->Merge(0, dwUnmergedLen, pUnmergedPortion, &pNewObj);
  4609. if(FAILED(hres))
  4610. return hres;
  4611. CReleaseMe rm1(pNewObj);
  4612. hres = pNewObj->SetDecoration(m_wszMachineName, m_wsNamespace);
  4613. if(FAILED(hres))
  4614. return hres;
  4615. hres = m_pClassCache->AssertClass(pNewObj, wszClassName, false,
  4616. nFakeUpdateTime, false);
  4617. if(FAILED(hres))
  4618. return hres;
  4619. return WBEM_S_NO_ERROR;
  4620. }
  4621. CHR CNamespaceHandle::ConstructInstanceDefName(LPWSTR wszInstanceDefName,
  4622. LPCWSTR wszKey)
  4623. {
  4624. wcscpy(wszInstanceDefName, A51_INSTDEF_FILE_PREFIX);
  4625. if(!Hash(wszKey, wszInstanceDefName + wcslen(A51_INSTDEF_FILE_PREFIX)))
  4626. {
  4627. return WBEM_E_OUT_OF_MEMORY;
  4628. }
  4629. return WBEM_S_NO_ERROR;
  4630. }
  4631. CHR CNamespaceHandle::ConstructInstDefNameFromLinkName(
  4632. LPWSTR wszInstanceDefName,
  4633. LPCWSTR wszInstanceLinkName)
  4634. {
  4635. wcscpy(wszInstanceDefName, A51_INSTDEF_FILE_PREFIX);
  4636. wcscat(wszInstanceDefName,
  4637. wszInstanceLinkName + wcslen(A51_INSTLINK_FILE_PREFIX));
  4638. return WBEM_S_NO_ERROR;
  4639. }
  4640. CHR CNamespaceHandle::ConstructClassDefFileName(LPCWSTR wszClassName,
  4641. LPWSTR wszFileName)
  4642. {
  4643. wcscpy(wszFileName, A51_CLASSDEF_FILE_PREFIX);
  4644. if(!Hash(wszClassName, wszFileName+wcslen(A51_CLASSDEF_FILE_PREFIX)))
  4645. return WBEM_E_INVALID_OBJECT;
  4646. return WBEM_S_NO_ERROR;
  4647. }
  4648. CHR CNamespaceHandle::ConstructClassDefFileNameFromHash(LPCWSTR wszHash,
  4649. LPWSTR wszFileName)
  4650. {
  4651. wcscpy(wszFileName, A51_CLASSDEF_FILE_PREFIX);
  4652. wcscat(wszFileName, wszHash);
  4653. return WBEM_S_NO_ERROR;
  4654. }
  4655. //=============================================================================
  4656. //
  4657. // CNamespaceHandle::CreateSystemClasses
  4658. //
  4659. // We are in a pseudo namespace. We need to determine if we already have
  4660. // the system classes in this namespace. The system classes that we create
  4661. // are those that exist in all namespaces, and no others. If they do not exist
  4662. // we create them.
  4663. // The whole creation process happens within the confines of a transaction
  4664. // that we create and own within this method.
  4665. //
  4666. //=============================================================================
  4667. HRESULT CNamespaceHandle::CreateSystemClasses(CFlexArray &aSystemClasses)
  4668. {
  4669. HRESULT hRes = WBEM_S_NO_ERROR;
  4670. //Now we need to determine if the system classes already exist. Lets do this by looking for the __thisnamespace
  4671. //class!
  4672. {
  4673. _IWmiObject *pObj = NULL;
  4674. hRes = GetClassDirect(L"__thisnamespace", IID__IWmiObject, (void**)&pObj, false, NULL, NULL, NULL);
  4675. if (SUCCEEDED(hRes))
  4676. {
  4677. //All done! They already exist!
  4678. pObj->Release();
  4679. return WBEM_S_NO_ERROR;
  4680. }
  4681. else if (hRes != WBEM_E_NOT_FOUND)
  4682. {
  4683. //Something went bad, so we just fail!
  4684. return hRes;
  4685. }
  4686. }
  4687. //There are no system classes so we need to create them.
  4688. hRes = A51TranslateErrorCode(g_Glob.GetFileCache()->BeginTransaction());
  4689. CEventCollector eventCollector;
  4690. _IWmiObject *Objects[256];
  4691. _IWmiObject **ppObjects = NULL;
  4692. ULONG uSize = 256;
  4693. if (SUCCEEDED(hRes) && aSystemClasses.Size())
  4694. {
  4695. //If we have a system-class array we need to use that instead of using the ones retrieved from the core
  4696. //not doing so will cause a mismatch. We retrieved these as part of the upgrade process...
  4697. uSize = aSystemClasses.Size();
  4698. ppObjects = (_IWmiObject**)&aSystemClasses[0];
  4699. }
  4700. else if (SUCCEEDED(hRes))
  4701. {
  4702. //None retrieved from upgrade process so we must be a clean install. Therefore we should
  4703. //get the list from the core...
  4704. _IWmiCoreServices * pSvcs = g_Glob.GetCoreSvcs();
  4705. CReleaseMe rm(pSvcs);
  4706. hRes = pSvcs->GetSystemObjects(GET_SYSTEM_STD_OBJECTS, &uSize, Objects);
  4707. ppObjects = Objects;
  4708. }
  4709. if (SUCCEEDED(hRes))
  4710. {
  4711. for (int i = 0; i < uSize; i++)
  4712. {
  4713. IWbemClassObject *pObj;
  4714. if (SUCCEEDED(hRes))
  4715. {
  4716. hRes = ppObjects[i]->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pObj);
  4717. if (SUCCEEDED(hRes))
  4718. {
  4719. hRes = PutObject(IID_IWbemClassObject, pObj, WMIDB_DISABLE_EVENTS, 0, 0, eventCollector);
  4720. pObj->Release();
  4721. if (FAILED(hRes))
  4722. {
  4723. ERRORTRACE((LOG_WBEMCORE, "Creation of system class failed during repository creation <0x%X>!\n", hRes));
  4724. }
  4725. }
  4726. }
  4727. ppObjects[i]->Release();
  4728. }
  4729. }
  4730. //Clear out the array that was sent to us.
  4731. aSystemClasses.Empty();
  4732. if (FAILED(hRes))
  4733. {
  4734. g_Glob.GetFileCache()->AbortTransaction();
  4735. }
  4736. else
  4737. {
  4738. hRes = A51TranslateErrorCode(g_Glob.GetFileCache()->CommitTransaction());
  4739. if (hRes == ERROR_SUCCESS)
  4740. CRepository::WriteOperationNotification();
  4741. else
  4742. CRepository::RecoverCheckpoint();
  4743. }
  4744. return hRes;
  4745. }
  4746. class CSystemClassDeletionSink : public CUnkBase<IWbemObjectSink, &IID_IWbemObjectSink>
  4747. {
  4748. CWStringArray &m_aChildNamespaces;
  4749. public:
  4750. CSystemClassDeletionSink(CWStringArray &aChildNamespaces)
  4751. : m_aChildNamespaces(aChildNamespaces)
  4752. {
  4753. }
  4754. ~CSystemClassDeletionSink()
  4755. {
  4756. }
  4757. STDMETHOD(Indicate)(long lNumObjects, IWbemClassObject** apObjects)
  4758. {
  4759. HRESULT hRes;
  4760. for (int i = 0; i != lNumObjects; i++)
  4761. {
  4762. if (apObjects[i] != NULL)
  4763. {
  4764. _IWmiObject *pInst = NULL;
  4765. hRes = apObjects[i]->QueryInterface(IID__IWmiObject, (void**)&pInst);
  4766. if (FAILED(hRes))
  4767. return hRes;
  4768. CReleaseMe rm(pInst);
  4769. BSTR strKey = NULL;
  4770. hRes = pInst->GetKeyString(0, &strKey);
  4771. if(FAILED(hRes))
  4772. return hRes;
  4773. CSysFreeMe sfm(strKey);
  4774. if (m_aChildNamespaces.Add(strKey) != CWStringArray::no_error)
  4775. return WBEM_E_OUT_OF_MEMORY;
  4776. }
  4777. }
  4778. return WBEM_S_NO_ERROR;
  4779. }
  4780. STDMETHOD(SetStatus)(long lFlags, HRESULT hresResult, BSTR, IWbemClassObject*)
  4781. {
  4782. return WBEM_S_NO_ERROR;
  4783. }
  4784. };
  4785. //=============================================================================
  4786. //=============================================================================
  4787. CDbIterator::CDbIterator(CLifeControl* pControl, bool bUseLock)
  4788. : TUnkBase(pControl), m_lCurrentIndex(0), m_hresStatus(WBEM_S_FALSE),
  4789. m_pMainFiber(NULL), m_pExecFiber(NULL), m_dwNumRequested(0),
  4790. m_pExecReq(NULL), m_hresCancellationStatus(WBEM_S_NO_ERROR),
  4791. m_bExecFiberRunning(false), m_bUseLock(bUseLock)
  4792. {
  4793. }
  4794. CDbIterator::~CDbIterator()
  4795. {
  4796. if(m_pExecFiber)
  4797. Cancel(0, NULL);
  4798. if(m_pExecReq)
  4799. delete m_pExecReq;
  4800. CRepository::ReadOperationNotification();
  4801. }
  4802. void CDbIterator::SetExecFiber(void* pFiber, CFiberTask* pReq)
  4803. {
  4804. m_pExecFiber = pFiber;
  4805. m_pExecReq = pReq;
  4806. }
  4807. STDMETHODIMP CDbIterator::Cancel(DWORD dwFlags, void* pFiber)
  4808. {
  4809. CInCritSec ics(&m_cs);
  4810. m_qObjects.Clear();
  4811. //
  4812. // Mark the iterator as cancelled and allow the execution fiber to resume
  4813. // and complete --- that guarantees that any memory it allocated will be
  4814. // cleaned up. The exception to this rule is if the fiber has not started
  4815. // execution yet; in that case, we do not want to switch to it, as it would
  4816. // have to run until the first Indicate to find out that it's been
  4817. // cancelled. (In the normal case, the execution fiber is suspended
  4818. // inside Indicate, so when we switch back we will immediately give it
  4819. // WBEM_E_CALL_CANCELLED so that it can clean up and return)
  4820. //
  4821. m_hresCancellationStatus = WBEM_E_CALL_CANCELLED;
  4822. if(m_pExecFiber)
  4823. {
  4824. if(m_bExecFiberRunning)
  4825. {
  4826. _ASSERT(m_pMainFiber == NULL && m_pExecFiber != NULL,
  4827. L"Fiber trouble");
  4828. //
  4829. // Make sure the calling thread has a fiber
  4830. //
  4831. m_pMainFiber = pFiber;
  4832. if(m_pMainFiber == NULL)
  4833. return WBEM_E_OUT_OF_MEMORY;
  4834. {
  4835. CAutoReadLock lock(&g_readWriteLock);
  4836. if (m_bUseLock)
  4837. {
  4838. if (!lock.Lock())
  4839. return WBEM_E_FAILED;
  4840. }
  4841. SwitchToFiber(m_pExecFiber);
  4842. }
  4843. }
  4844. //
  4845. // At this point, the executing fiber is dead. We know, because in the
  4846. // cancelled state we do not switch to the main fiber in Indicate.
  4847. //
  4848. ReturnFiber(m_pExecFiber);
  4849. m_pExecFiber = NULL;
  4850. }
  4851. return S_OK;
  4852. }
  4853. STDMETHODIMP CDbIterator::NextBatch(
  4854. DWORD dwNumRequested,
  4855. DWORD dwTimeOutSeconds,
  4856. DWORD dwFlags,
  4857. DWORD dwRequestedHandleType,
  4858. REFIID riid,
  4859. void* pFiber,
  4860. DWORD *pdwNumReturned,
  4861. LPVOID *ppObjects
  4862. )
  4863. {
  4864. CInCritSec ics(&m_cs);
  4865. //
  4866. // TEMP CODE: Someone is calling us on an impersonated thread. Let's catch
  4867. // the, ahem, bastard
  4868. //
  4869. HANDLE hToken;
  4870. BOOL bRes = OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken);
  4871. if(bRes)
  4872. {
  4873. //_ASSERT(false, L"Called with a thread token");
  4874. ERRORTRACE((LOG_WBEMCORE, "Repository called with a thread token! "
  4875. "It shall be removed\n"));
  4876. CloseHandle(hToken);
  4877. SetThreadToken(NULL, NULL);
  4878. }
  4879. _ASSERT(SUCCEEDED(m_hresCancellationStatus), L"Next called after Cancel");
  4880. m_bExecFiberRunning = true;
  4881. //
  4882. // Wait until it's over or the right number of objects has been received
  4883. //
  4884. if(m_qObjects.GetQueueSize() < dwNumRequested)
  4885. {
  4886. _ASSERT(m_pMainFiber == NULL && m_pExecFiber != NULL, L"Fiber trouble");
  4887. //
  4888. // Make sure the calling thread has a fiber
  4889. //
  4890. m_pMainFiber = pFiber;
  4891. if(m_pMainFiber == NULL)
  4892. return WBEM_E_OUT_OF_MEMORY;
  4893. m_dwNumRequested = dwNumRequested;
  4894. //
  4895. // We need to acquire the read lock for the duration of the continuation
  4896. // of the retrieval
  4897. //
  4898. {
  4899. CAutoReadLock lock(&g_readWriteLock);
  4900. if (m_bUseLock)
  4901. {
  4902. if (!lock.Lock())
  4903. {
  4904. m_pMainFiber = NULL;
  4905. return WBEM_E_FAILED;
  4906. }
  4907. }
  4908. if (g_bShuttingDown)
  4909. {
  4910. m_pMainFiber = NULL;
  4911. return WBEM_E_SHUTTING_DOWN;
  4912. }
  4913. SwitchToFiber(m_pExecFiber);
  4914. }
  4915. m_pMainFiber = NULL;
  4916. }
  4917. //
  4918. // We have as much as we are going to have!
  4919. //
  4920. DWORD dwReqIndex = 0;
  4921. while(dwReqIndex < dwNumRequested)
  4922. {
  4923. if(0 == m_qObjects.GetQueueSize())
  4924. {
  4925. //
  4926. // That's it --- we waited for production, so there are simply no
  4927. // more objects in the enumeration
  4928. //
  4929. *pdwNumReturned = dwReqIndex;
  4930. return m_hresStatus;
  4931. }
  4932. IWbemClassObject* pObj = m_qObjects.Dequeue();
  4933. CReleaseMe rm1(pObj);
  4934. pObj->QueryInterface(riid, ppObjects + dwReqIndex);
  4935. dwReqIndex++;
  4936. }
  4937. //
  4938. // Got everything
  4939. //
  4940. *pdwNumReturned= dwNumRequested;
  4941. return S_OK;
  4942. }
  4943. HRESULT CDbIterator::Indicate(long lNumObjects, IWbemClassObject** apObjects)
  4944. {
  4945. if(FAILED(m_hresCancellationStatus))
  4946. {
  4947. //
  4948. // Screw-up --- the fiber called back with Indicate even after we
  4949. // cancelled! Oh well.
  4950. //
  4951. _ASSERT(false, L"Execution code ignored cancel return code!");
  4952. return m_hresCancellationStatus;
  4953. }
  4954. //
  4955. // Add the objects received to the array
  4956. //
  4957. for(long i = 0; i < lNumObjects; i++)
  4958. {
  4959. m_qObjects.Enqueue(apObjects[i]);
  4960. }
  4961. //
  4962. // Check if we have compiled enough for the current request and should
  4963. // therefore interrupt the gatherer
  4964. //
  4965. if(m_qObjects.GetQueueSize() >= m_dwNumRequested)
  4966. {
  4967. //
  4968. // Switch us back to the original fiber
  4969. //
  4970. SwitchToFiber(m_pMainFiber);
  4971. }
  4972. return m_hresCancellationStatus;
  4973. }
  4974. HRESULT CDbIterator::SetStatus(long lFlags, HRESULT hresResult,
  4975. BSTR, IWbemClassObject*)
  4976. {
  4977. _ASSERT(m_hresStatus == WBEM_S_FALSE, L"SetStatus called twice!");
  4978. _ASSERT(lFlags == WBEM_STATUS_COMPLETE, L"SetStatus flags invalid");
  4979. m_hresStatus = hresResult;
  4980. //
  4981. // Switch us back to the original thread, we are done
  4982. //
  4983. m_bExecFiberRunning = false;
  4984. SwitchToFiber(m_pMainFiber);
  4985. return WBEM_S_NO_ERROR;
  4986. }
  4987. CRepEvent::CRepEvent(DWORD dwType, LPCWSTR wszNamespace, LPCWSTR wszArg1,
  4988. _IWmiObject* pObj1, _IWmiObject* pObj2)
  4989. {
  4990. m_dwType = dwType;
  4991. m_pObj1 = 0;
  4992. m_pObj2 = 0;
  4993. m_wszArg1 = m_wszNamespace = NULL;
  4994. if (wszArg1)
  4995. {
  4996. m_wszArg1 = (WCHAR*)TempAlloc((wcslen(wszArg1)+1)*sizeof(WCHAR));
  4997. if (m_wszArg1 == NULL)
  4998. throw CX_MemoryException();
  4999. wcscpy(m_wszArg1, wszArg1);
  5000. }
  5001. if (wszNamespace)
  5002. {
  5003. m_wszNamespace = (WCHAR*)TempAlloc((wcslen(wszNamespace)+1)*sizeof(WCHAR));
  5004. if (m_wszNamespace == NULL)
  5005. throw CX_MemoryException();
  5006. wcscpy(m_wszNamespace, wszNamespace);
  5007. }
  5008. if (pObj1)
  5009. {
  5010. m_pObj1 = pObj1;
  5011. pObj1->AddRef();
  5012. }
  5013. if (pObj2)
  5014. {
  5015. m_pObj2 = pObj2;
  5016. pObj2->AddRef();
  5017. }
  5018. }
  5019. CRepEvent::~CRepEvent()
  5020. {
  5021. TempFree(m_wszArg1, (wcslen(m_wszArg1)+1)*sizeof(WCHAR));
  5022. TempFree(m_wszNamespace, (wcslen(m_wszNamespace)+1)*sizeof(WCHAR));
  5023. if (m_pObj1)
  5024. m_pObj1->Release();
  5025. if (m_pObj2)
  5026. m_pObj2->Release();
  5027. };
  5028. HRESULT CEventCollector::SendEvents(_IWmiCoreServices* pCore)
  5029. {
  5030. HRESULT hresGlobal = WBEM_S_NO_ERROR;
  5031. for (int i = 0; i != m_apEvents.GetSize(); i++)
  5032. {
  5033. CRepEvent *pEvent = m_apEvents[i];
  5034. _IWmiObject* apObjs[2];
  5035. apObjs[0] = pEvent->m_pObj1;
  5036. apObjs[1] = pEvent->m_pObj2;
  5037. HRESULT hres = pCore->DeliverIntrinsicEvent(
  5038. pEvent->m_wszNamespace, pEvent->m_dwType, NULL,
  5039. pEvent->m_wszArg1, NULL, (pEvent->m_pObj2?2:1), apObjs);
  5040. if(FAILED(hres))
  5041. hresGlobal = hres;
  5042. }
  5043. return hresGlobal;
  5044. }
  5045. bool CEventCollector::AddEvent(CRepEvent* pEvent)
  5046. {
  5047. EnterCriticalSection(&m_csLock);
  5048. if(m_bNamespaceOnly)
  5049. {
  5050. if(pEvent->m_dwType != WBEM_EVENTTYPE_NamespaceCreation &&
  5051. pEvent->m_dwType != WBEM_EVENTTYPE_NamespaceDeletion &&
  5052. pEvent->m_dwType != WBEM_EVENTTYPE_NamespaceModification)
  5053. {
  5054. delete pEvent;
  5055. LeaveCriticalSection(&m_csLock);
  5056. return true;
  5057. }
  5058. }
  5059. bool bRet = (m_apEvents.Add(pEvent) >= 0);
  5060. LeaveCriticalSection(&m_csLock);
  5061. return bRet;
  5062. }
  5063. void CEventCollector::DeleteAllEvents()
  5064. {
  5065. EnterCriticalSection(&m_csLock);
  5066. m_bNamespaceOnly = false;
  5067. m_apEvents.RemoveAll();
  5068. LeaveCriticalSection(&m_csLock);
  5069. }
  5070. void CEventCollector::TransferEvents(CEventCollector &aEventsToTransfer)
  5071. {
  5072. m_bNamespaceOnly = aEventsToTransfer.m_bNamespaceOnly;
  5073. while(aEventsToTransfer.m_apEvents.GetSize())
  5074. {
  5075. CRepEvent *pEvent = 0;
  5076. aEventsToTransfer.m_apEvents.RemoveAt(0, &pEvent);
  5077. m_apEvents.Add(pEvent);
  5078. }
  5079. }