Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6255 lines
154 KiB

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