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

6227 lines
172 KiB

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