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.

995 lines
23 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. #include "a51conv.h"
  19. #include "A51Exp.h"
  20. #include "A51Imp.h"
  21. CLock g_readWriteLock;
  22. bool g_bShuttingDown = false;
  23. CNamespaceHandle *g_pSystemClassNamespace = NULL;
  24. DWORD g_dwOldRepositoryVersion = 0;
  25. DWORD g_dwCurrentRepositoryVersion = 0;
  26. DWORD g_ShutDownFlags = 0;
  27. //*****************************************************************************
  28. HRESULT CRepository::Initialize()
  29. {
  30. HRESULT hRes = WBEM_E_FAILED;
  31. InitializeRepositoryVersions();
  32. //
  33. // Make sure that the version that created the repository is the same
  34. // as the one we are currently running
  35. //
  36. hRes = UpgradeRepositoryFormatPhase1();
  37. //
  38. // Initialize time index
  39. //
  40. if (SUCCEEDED(hRes))
  41. {
  42. FILETIME ft;
  43. GetSystemTimeAsFileTime(&ft);
  44. g_nCurrentTime = ft.dwLowDateTime + ((__int64)ft.dwHighDateTime << 32);
  45. }
  46. //
  47. // Get the repository directory
  48. //
  49. if (SUCCEEDED(hRes))
  50. hRes = GetRepositoryDirectory();
  51. //
  52. // initialze all our global resources
  53. //
  54. if (SUCCEEDED(hRes))
  55. hRes = InitializeGlobalVariables();
  56. hRes = g_Glob.GetFileCache()->Initialize(g_Glob.GetRootDir());
  57. //
  58. // Initialize class cache. It will read the registry itself to find out
  59. // its size limitations
  60. //
  61. if (SUCCEEDED(hRes))
  62. {
  63. hRes = g_Glob.Initialize();
  64. if(hRes != ERROR_SUCCESS)
  65. {
  66. hRes = WBEM_E_FAILED;
  67. }
  68. }
  69. //if (SUCCEEDED(hRes))
  70. //{
  71. // hRes = CoCreateInstance(CLSID_IWmiCoreServices, NULL,
  72. // CLSCTX_INPROC_SERVER, IID__IWmiCoreServices,
  73. // (void**)&g_pCoreServices);
  74. //}
  75. //Run phase 2 of the repository upgrade
  76. if (SUCCEEDED(hRes))
  77. {
  78. hRes = UpgradeRepositoryFormatPhase2();
  79. }
  80. //If we need to create the system class namespace then go ahead and do that...
  81. if (SUCCEEDED(hRes))
  82. {
  83. g_pSystemClassNamespace = new CNamespaceHandle(m_pControl, this);
  84. if (g_pSystemClassNamespace == NULL)
  85. {
  86. hRes = WBEM_E_OUT_OF_MEMORY;
  87. }
  88. }
  89. if (SUCCEEDED(hRes))
  90. {
  91. g_pSystemClassNamespace->AddRef();
  92. hRes = g_pSystemClassNamespace->Initialize(A51_SYSTEMCLASS_NS);
  93. }
  94. if (SUCCEEDED(hRes))
  95. {
  96. hRes = g_pSystemClassNamespace->CreateSystemClasses(m_aSystemClasses);
  97. }
  98. //Run phase 3 of the repository upgrade
  99. if (SUCCEEDED(hRes))
  100. {
  101. hRes = UpgradeRepositoryFormatPhase3();
  102. }
  103. if (SUCCEEDED(hRes))
  104. g_bShuttingDown = false;
  105. else
  106. {
  107. g_Glob.GetFileCache()->Uninitialize(0);
  108. g_Glob.GetForestCache()->Deinitialize();
  109. if (g_pSystemClassNamespace)
  110. {
  111. delete g_pSystemClassNamespace;
  112. g_pSystemClassNamespace = NULL;
  113. }
  114. }
  115. return hRes;
  116. }
  117. HRESULT CRepository::InitializeRepositoryVersions()
  118. {
  119. DWORD dwVal = 0;
  120. CPersistentConfig cfg;
  121. cfg.GetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, dwVal);
  122. if (dwVal == 0)
  123. dwVal = A51_REP_FS_VERSION;
  124. g_dwOldRepositoryVersion = dwVal;
  125. g_dwCurrentRepositoryVersion = A51_REP_FS_VERSION;
  126. return WBEM_S_NO_ERROR;
  127. }
  128. HRESULT CRepository::UpgradeRepositoryFormatPhase1()
  129. {
  130. HRESULT hRes = WBEM_E_DATABASE_VER_MISMATCH;
  131. CPersistentConfig cfg;
  132. DWORD dwVal = 0;
  133. if (!cfg.GetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, dwVal)
  134. ||
  135. (dwVal == 2))
  136. {
  137. ERRORTRACE((LOG_WBEMCORE, "Repository format upgrade from version 2 to version 3 taking place. Performing file-based to object store upgrade\n"));
  138. hRes = ConvertA51ToRoswell();
  139. if(hRes != ERROR_SUCCESS)
  140. {
  141. ERRORTRACE((LOG_WBEMCORE, "Repository cannot initialize "
  142. "due to a failure in repository upgrade from file-based repository to object store\n"));
  143. return WBEM_E_DATABASE_VER_MISMATCH;
  144. }
  145. dwVal = 3;
  146. cfg.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, dwVal);
  147. }
  148. else if (dwVal == 0)
  149. {
  150. //
  151. // First time --- write the right version in
  152. //
  153. hRes = WBEM_S_NO_ERROR;
  154. cfg.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION,
  155. A51_REP_FS_VERSION);
  156. }
  157. else if (dwVal > 2)
  158. hRes = WBEM_S_NO_ERROR;
  159. if (hRes == WBEM_E_DATABASE_VER_MISMATCH)
  160. {
  161. //
  162. // Unsupported version
  163. //
  164. ERRORTRACE((LOG_WBEMCORE, "Repository cannot initialize "
  165. "due to the detection of an unknown repository version. Version found = <%ld>, version expected = <%ld>\n", dwVal, A51_REP_FS_VERSION ));
  166. return WBEM_E_DATABASE_VER_MISMATCH;
  167. }
  168. return hRes;
  169. }
  170. HRESULT CRepository::UpgradeRepositoryFormatPhase2()
  171. {
  172. HRESULT hRes = WBEM_E_DATABASE_VER_MISMATCH;
  173. CPersistentConfig cfg;
  174. DWORD dwVal = 0;
  175. if (!cfg.GetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, dwVal)
  176. ||
  177. (dwVal == 3))
  178. {
  179. ERRORTRACE((LOG_WBEMCORE, "Repository format upgrade from version 3 to version 4 taking place. Deleting all redundant system classes\n"));
  180. hRes = DeleteSystemClassesFromNamespaces();
  181. if(FAILED(hRes))
  182. {
  183. ERRORTRACE((LOG_WBEMCORE, "Repository cannot initialize "
  184. "due to a failure in repository upgrade while deleting all redundant system classes\n"));
  185. return WBEM_E_DATABASE_VER_MISMATCH;
  186. }
  187. dwVal = 4;
  188. cfg.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, dwVal);
  189. }
  190. else if (dwVal > 3)
  191. hRes = WBEM_S_NO_ERROR;
  192. if (hRes == WBEM_E_DATABASE_VER_MISMATCH)
  193. {
  194. //
  195. // Unsupported version
  196. //
  197. ERRORTRACE((LOG_WBEMCORE, "Repository cannot initialize "
  198. "due to the detection of an unknown repository version. Version found = <%ld>, version expected = <%ld>\n", dwVal, A51_REP_FS_VERSION ));
  199. return WBEM_E_DATABASE_VER_MISMATCH;
  200. }
  201. return hRes;
  202. }
  203. HRESULT CRepository::UpgradeRepositoryFormatPhase3()
  204. {
  205. HRESULT hRes = WBEM_E_DATABASE_VER_MISMATCH;
  206. CPersistentConfig cfg;
  207. DWORD dwVal = 0;
  208. if (!cfg.GetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, dwVal)
  209. ||
  210. (dwVal == 4))
  211. {
  212. ERRORTRACE((LOG_WBEMCORE, "Repository format upgrade from version 4 to version 5 taking place. Upgrading some system classes\n"));
  213. hRes = UpgradeSystemClasses();
  214. if (FAILED(hRes))
  215. {
  216. ERRORTRACE((LOG_WBEMCORE, "Repository cannot initialize "
  217. "due to a failure in repository upgrade while upgrading system classes\n"));
  218. return WBEM_E_DATABASE_VER_MISMATCH;
  219. }
  220. dwVal = 5;
  221. cfg.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, dwVal);
  222. }
  223. else if (dwVal > 4)
  224. hRes = WBEM_S_NO_ERROR;
  225. if (hRes == WBEM_E_DATABASE_VER_MISMATCH)
  226. {
  227. //
  228. // Unsupported version
  229. //
  230. ERRORTRACE((LOG_WBEMCORE, "Repository cannot initialize "
  231. "due to the detection of an unknown repository version. Version found = <%ld>, version expected = <%ld>\n", dwVal, A51_REP_FS_VERSION ));
  232. return WBEM_E_DATABASE_VER_MISMATCH;
  233. }
  234. return hRes;
  235. }
  236. HRESULT CRepository::GetRepositoryDirectory()
  237. {
  238. HKEY hKey;
  239. long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  240. L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
  241. 0, KEY_READ, &hKey);
  242. if(lRes)
  243. return WBEM_E_FAILED;
  244. CFileName wszTmp;
  245. if (wszTmp == NULL)
  246. return WBEM_E_OUT_OF_MEMORY;
  247. DWORD dwLen = wszTmp.Length();
  248. lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL,
  249. (LPBYTE)(wchar_t*)wszTmp, &dwLen);
  250. RegCloseKey(hKey);
  251. if(lRes)
  252. return WBEM_E_FAILED;
  253. CFileName wszRepDir;
  254. if (wszRepDir == NULL)
  255. return WBEM_E_OUT_OF_MEMORY;
  256. if (ExpandEnvironmentStringsW(wszTmp,wszRepDir,wszTmp.Length()) == 0)
  257. return WBEM_E_FAILED;
  258. lRes = EnsureDirectory(wszRepDir);
  259. if(lRes != ERROR_SUCCESS)
  260. return WBEM_E_FAILED;
  261. //
  262. // Append standard postfix --- that is our root
  263. //
  264. wcscpy(g_Glob.GetRootDir(), wszRepDir);
  265. wcscat(g_Glob.GetRootDir(), L"\\FS");
  266. g_Glob.SetRootDirLen(wcslen(g_Glob.GetRootDir()));
  267. //
  268. // Ensure the directory is there
  269. //
  270. lRes = EnsureDirectory(g_Glob.GetRootDir());
  271. if(lRes != ERROR_SUCCESS)
  272. return WBEM_E_FAILED;
  273. SetFileAttributesW(g_Glob.GetRootDir(), FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
  274. return WBEM_S_NO_ERROR;
  275. }
  276. HRESULT CRepository::InitializeGlobalVariables()
  277. {
  278. //g_Glob.GetFileCache() = new CFileCache;
  279. //if (g_Glob.GetFileCache() == NULL)
  280. //{
  281. // return WBEM_E_OUT_OF_MEMORY;
  282. //}
  283. //g_Glob.GetFileCache()->AddRef();
  284. //g_ForestCache = new CForestCache;
  285. //if (g_ForestCache == NULL)
  286. //{
  287. // g_Glob.GetFileCache()->Release();
  288. // g_Glob.GetFileCache() = NULL;
  289. // return WBEM_E_OUT_OF_MEMORY;
  290. //}
  291. //g_ForestCache->AddRef();
  292. return WBEM_S_NO_ERROR;
  293. }
  294. HRESULT DoAutoDatabaseRestore()
  295. {
  296. HRESULT hRes = WBEM_S_NO_ERROR;
  297. //We may need to do a database restore!
  298. CFileName wszBackupFile;
  299. if (wszBackupFile == NULL)
  300. {
  301. return WBEM_E_OUT_OF_MEMORY;
  302. }
  303. int nLen = g_Glob.GetRootDirLen();
  304. wcsncpy(wszBackupFile, g_Glob.GetRootDir(), nLen - 3); // exclude "\FS" from path
  305. wszBackupFile[nLen - 3] = '\0';
  306. wcscat(wszBackupFile, L"\\repdrvfs.rec");
  307. DWORD dwAttributes = GetFileAttributesW(wszBackupFile);
  308. if (dwAttributes != -1)
  309. {
  310. DWORD dwMask = FILE_ATTRIBUTE_DEVICE |
  311. FILE_ATTRIBUTE_DIRECTORY |
  312. FILE_ATTRIBUTE_OFFLINE |
  313. FILE_ATTRIBUTE_REPARSE_POINT |
  314. FILE_ATTRIBUTE_SPARSE_FILE;
  315. if (!(dwAttributes & dwMask))
  316. {
  317. CRepositoryPackager packager;
  318. hRes = packager.UnpackageRepository(wszBackupFile);
  319. //We are going to ignore the error so if there was a problem we will just
  320. //load all the standard MOFs.
  321. if (hRes != WBEM_E_OUT_OF_MEMORY)
  322. hRes = WBEM_S_NO_ERROR;
  323. }
  324. }
  325. return hRes;
  326. }
  327. HRESULT CRepository::DeleteSystemClassesFromNamespaces()
  328. {
  329. HRESULT hRes = WBEM_S_NO_ERROR;
  330. CSession* pSession = new CSession(m_pControl);
  331. if (pSession == NULL)
  332. return WBEM_E_OUT_OF_MEMORY;
  333. CReleaseMe rm1(pSession);
  334. pSession->AddRef();
  335. CNamespaceHandle* pHandle = new CNamespaceHandle(m_pControl, this);
  336. if (pHandle == NULL)
  337. {
  338. return WBEM_E_OUT_OF_MEMORY;
  339. }
  340. CReleaseMe rm2(pHandle);
  341. pHandle->AddRef();
  342. hRes = pHandle->Initialize(L"root");
  343. if (FAILED(hRes))
  344. return hRes;
  345. CWStringArray aSystemClasses;
  346. CWStringArray aSystemClassesSuperclass;
  347. _IWmiObject *Objects[256];
  348. ULONG uSize = 256;
  349. _IWmiCoreServices * pSvcs = g_Glob.GetCoreSvcs();
  350. CReleaseMe rm(pSvcs);
  351. hRes = pSvcs->GetSystemObjects(GET_SYSTEM_STD_OBJECTS, &uSize, Objects);
  352. if (FAILED(hRes))
  353. return hRes;
  354. for (int i = 0; i < uSize; i++)
  355. {
  356. IWbemClassObject *pObj = NULL;
  357. if (SUCCEEDED(hRes))
  358. {
  359. hRes = Objects[i]->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pObj);
  360. if (SUCCEEDED(hRes))
  361. {
  362. VARIANT var;
  363. VariantInit(&var);
  364. hRes = pObj->Get(L"__CLASS", 0, &var, NULL, NULL);
  365. if (SUCCEEDED(hRes) && (V_VT(&var) == VT_BSTR))
  366. {
  367. //PCA: Retrieve the object from the root namespace so we can re-add it to the
  368. // new __systemclass namespace.
  369. _IWmiObject *pObj = NULL;
  370. hRes = pHandle->GetObjectByPath(V_BSTR(&var), 0, IID__IWmiObject, (void**)&pObj);
  371. if (SUCCEEDED(hRes))
  372. {
  373. if (m_aSystemClasses.Add(pObj) != CFlexArray::no_error)
  374. hRes = WBEM_E_FAILED;
  375. }
  376. if (SUCCEEDED(hRes) && (aSystemClasses.Add(V_BSTR(&var)) != CWStringArray::no_error))
  377. hRes = WBEM_E_FAILED;
  378. }
  379. else
  380. hRes = WBEM_E_FAILED;
  381. VariantClear(&var);
  382. }
  383. if (SUCCEEDED(hRes))
  384. {
  385. VARIANT var;
  386. VariantInit(&var);
  387. hRes = pObj->Get(L"__SUPERCLASS", 0, &var, NULL, NULL);
  388. if (SUCCEEDED(hRes) && (V_VT(&var) == VT_BSTR))
  389. {
  390. if (aSystemClassesSuperclass.Add(V_BSTR(&var)) != CWStringArray::no_error)
  391. hRes = WBEM_E_FAILED;
  392. }
  393. else if (SUCCEEDED(hRes) && (V_VT(&var) == VT_NULL))
  394. {
  395. if (aSystemClassesSuperclass.Add(L"") != CWStringArray::no_error)
  396. hRes = WBEM_E_FAILED;
  397. }
  398. else
  399. hRes = WBEM_E_FAILED;
  400. VariantClear(&var);
  401. }
  402. if (pObj)
  403. pObj->Release();
  404. }
  405. Objects[i]->Release();
  406. }
  407. if (FAILED(hRes))
  408. return hRes;
  409. hRes = pSession->BeginWriteTransaction(0);
  410. if (FAILED(hRes))
  411. return hRes;
  412. try
  413. {
  414. hRes = pHandle->RecursiveDeleteSystemClasses(aSystemClasses, aSystemClassesSuperclass);
  415. }
  416. catch (...)
  417. {
  418. hRes = WBEM_E_CRITICAL_ERROR;
  419. }
  420. if (FAILED(hRes))
  421. pSession->AbortTransaction(0);
  422. else
  423. pSession->CommitTransaction(0);
  424. return hRes;
  425. }
  426. HRESULT CRepository::UpgradeSystemClasses()
  427. {
  428. HRESULT hRes = WBEM_S_NO_ERROR;
  429. bool bNeedToRestoreOldRepository = false;
  430. wchar_t *wszExportFilename = new wchar_t[g_Glob.GetRootDirLen() + lstrlenW(L"\\upgrade.exp") + 1];
  431. if (wszExportFilename == NULL)
  432. hRes = WBEM_E_OUT_OF_MEMORY;
  433. CVectorDeleteMe<wchar_t> vdm1(wszExportFilename);
  434. wchar_t *wszImportFilename = new wchar_t[g_Glob.GetRootDirLen() + lstrlenW(L".bak\\upgrade.exp") + 1];
  435. if (wszImportFilename == NULL)
  436. hRes = WBEM_E_OUT_OF_MEMORY;
  437. CVectorDeleteMe<wchar_t> vdm2(wszImportFilename );
  438. wchar_t *wszBackupRepositoryDirectory = new wchar_t[g_Glob.GetRootDirLen() + lstrlenW(L".bak") + 1];
  439. if (wszBackupRepositoryDirectory == NULL)
  440. hRes = WBEM_E_OUT_OF_MEMORY;
  441. CVectorDeleteMe<wchar_t> vdm3(wszBackupRepositoryDirectory);
  442. if (SUCCEEDED(hRes))
  443. {
  444. lstrcpyW(wszExportFilename, g_Glob.GetRootDir());
  445. lstrcatW(wszExportFilename, L"\\upgrade.exp");
  446. lstrcpyW(wszImportFilename , g_Glob.GetRootDir());
  447. lstrcatW(wszImportFilename , L".bak\\upgrade.exp");
  448. lstrcpyW(wszBackupRepositoryDirectory, g_Glob.GetRootDir());
  449. lstrcatW(wszBackupRepositoryDirectory, L".bak");
  450. }
  451. if (SUCCEEDED(hRes))
  452. {
  453. A51Export exporter(m_pControl);
  454. hRes = exporter.Export(wszExportFilename, 0, this);
  455. }
  456. if (SUCCEEDED(hRes))
  457. {
  458. //Now need to shutdown the repository...
  459. g_Glob.GetFileCache()->Uninitialize(0);
  460. g_Glob.GetForestCache()->Deinitialize();
  461. //g_ForestCache = NULL;
  462. g_pSystemClassNamespace->Release();
  463. g_pSystemClassNamespace = NULL;
  464. //Move it sideways for safe keeping...
  465. MoveFile(g_Glob.GetRootDir() , wszBackupRepositoryDirectory);
  466. bNeedToRestoreOldRepository = true;
  467. //Restart the repository...
  468. hRes = InitializeGlobalVariables();
  469. if (SUCCEEDED(hRes))
  470. {
  471. hRes = EnsureDirectory(g_Glob.GetRootDir() );
  472. if(hRes != ERROR_SUCCESS)
  473. hRes = WBEM_E_FAILED;
  474. }
  475. if (SUCCEEDED(hRes))
  476. {
  477. hRes = g_Glob.GetFileCache()->Initialize(g_Glob.GetRootDir() );
  478. if(hRes != ERROR_SUCCESS)
  479. {
  480. hRes = WBEM_E_FAILED;
  481. }
  482. }
  483. if (SUCCEEDED(hRes))
  484. {
  485. hRes = g_Glob.Initialize();
  486. if(hRes != ERROR_SUCCESS)
  487. {
  488. hRes = WBEM_E_FAILED;
  489. }
  490. }
  491. if (SUCCEEDED(hRes))
  492. {
  493. g_pSystemClassNamespace = new CNamespaceHandle(m_pControl, this);
  494. if (g_pSystemClassNamespace == NULL)
  495. {
  496. hRes = WBEM_E_OUT_OF_MEMORY;
  497. }
  498. }
  499. if (SUCCEEDED(hRes))
  500. {
  501. g_pSystemClassNamespace->AddRef();
  502. hRes = g_pSystemClassNamespace->Initialize(A51_SYSTEMCLASS_NS);
  503. }
  504. if (SUCCEEDED(hRes))
  505. {
  506. //Need to re-create the system class namespace
  507. hRes = g_pSystemClassNamespace->CreateSystemClasses(m_aSystemClasses);
  508. }
  509. }
  510. if (SUCCEEDED(hRes))
  511. {
  512. A51Import importer;
  513. hRes = importer.Import(wszImportFilename, 0, this);
  514. }
  515. if (FAILED(hRes) && bNeedToRestoreOldRepository)
  516. {
  517. //Shutdown the repository
  518. g_Glob.GetFileCache()->Uninitialize(0);
  519. g_Glob.Deinitialize();
  520. if (g_pSystemClassNamespace)
  521. g_pSystemClassNamespace->Release();
  522. g_pSystemClassNamespace = NULL;
  523. //Delete the new directory (if it exists)
  524. A51RemoveDirectory(g_Glob.GetRootDir() );
  525. //Restore the old one
  526. MoveFile(wszBackupRepositoryDirectory, g_Glob.GetRootDir() );
  527. }
  528. else if (bNeedToRestoreOldRepository)
  529. {
  530. A51RemoveDirectory(wszBackupRepositoryDirectory);
  531. }
  532. //Delete the export file as we are done with it
  533. if (wszExportFilename)
  534. DeleteFile(wszExportFilename);
  535. return hRes;
  536. }
  537. HRESULT STDMETHODCALLTYPE CRepository::Logon(
  538. WMIDB_LOGON_TEMPLATE *pLogonParms,
  539. DWORD dwFlags,
  540. DWORD dwRequestedHandleType,
  541. IWmiDbSession **ppSession,
  542. IWmiDbHandle **ppRootNamespace
  543. )
  544. {
  545. //If not initialized, initialize all subsystems...
  546. if (!g_Glob.IsInit())
  547. {
  548. HRESULT hres = Initialize();
  549. if (FAILED(hres))
  550. return hres;
  551. }
  552. CSession* pSession = new CSession(m_pControl);
  553. if (pSession == NULL)
  554. return WBEM_E_OUT_OF_MEMORY;
  555. pSession->AddRef();
  556. CReleaseMe rm1(pSession);
  557. CNamespaceHandle* pHandle = new CNamespaceHandle(m_pControl, this);
  558. if (pHandle == NULL)
  559. return WBEM_E_OUT_OF_MEMORY;
  560. pHandle->AddRef();
  561. CTemplateReleaseMe<CNamespaceHandle> rm2(pHandle);
  562. HRESULT hres = pHandle->Initialize(L"");
  563. if(FAILED(hres))
  564. return hres;
  565. *ppRootNamespace = pHandle;
  566. pHandle->AddRef();
  567. *ppSession = pSession;
  568. pSession->AddRef();
  569. return S_OK;
  570. }
  571. HRESULT STDMETHODCALLTYPE CRepository::GetLogonTemplate(
  572. LCID lLocale,
  573. DWORD dwFlags,
  574. WMIDB_LOGON_TEMPLATE **ppLogonTemplate
  575. )
  576. {
  577. WMIDB_LOGON_TEMPLATE* lt = (WMIDB_LOGON_TEMPLATE*)CoTaskMemAlloc(sizeof(WMIDB_LOGON_TEMPLATE));
  578. lt->dwArraySize = 0;
  579. lt->pParm = NULL;
  580. *ppLogonTemplate = lt;
  581. return S_OK;
  582. }
  583. HRESULT STDMETHODCALLTYPE CRepository::FreeLogonTemplate(
  584. WMIDB_LOGON_TEMPLATE **ppTemplate
  585. )
  586. {
  587. CoTaskMemFree(*ppTemplate);
  588. *ppTemplate = NULL;
  589. return S_OK;
  590. }
  591. HRESULT STDMETHODCALLTYPE CRepository::Shutdown(
  592. DWORD dwFlags
  593. )
  594. {
  595. g_bShuttingDown = true;
  596. g_readWriteLock.WriteLock();
  597. g_ShutDownFlags = dwFlags;
  598. if (WMIDB_SHUTDOWN_MACHINE_DOWN != dwFlags)
  599. {
  600. if (g_pSystemClassNamespace)
  601. g_pSystemClassNamespace->Release();
  602. g_pSystemClassNamespace = NULL;
  603. g_Glob.GetForestCache()->Deinitialize();
  604. }
  605. g_Glob.GetFileCache()->Uninitialize(dwFlags);
  606. if (WMIDB_SHUTDOWN_MACHINE_DOWN != dwFlags)
  607. {
  608. g_Glob.Deinitialize();
  609. g_readWriteLock.WriteUnlock();
  610. }
  611. return S_OK;
  612. }
  613. HRESULT STDMETHODCALLTYPE CRepository::SetCallTimeout(
  614. DWORD dwMaxTimeout
  615. )
  616. {
  617. return S_OK;
  618. }
  619. HRESULT STDMETHODCALLTYPE CRepository::SetCacheValue(
  620. DWORD dwMaxBytes
  621. )
  622. {
  623. HKEY hKey;
  624. long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  625. L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
  626. 0, KEY_READ | KEY_WRITE, &hKey);
  627. if(lRes)
  628. return lRes;
  629. CRegCloseMe cm(hKey);
  630. DWORD dwLen = sizeof(DWORD);
  631. DWORD dwMaxAge;
  632. lRes = RegQueryValueExW(hKey, L"Max Class Cache Item Age (ms)", NULL, NULL,
  633. (LPBYTE)&dwMaxAge, &dwLen);
  634. if(lRes != ERROR_SUCCESS)
  635. {
  636. dwMaxAge = 10000;
  637. lRes = RegSetValueExW(hKey, L"Max Class Cache Item Age (ms)", 0,
  638. REG_DWORD, (LPBYTE)&dwMaxAge, sizeof(DWORD));
  639. }
  640. g_Glob.GetForestCache()->SetMaxMemory(dwMaxBytes, dwMaxAge);
  641. return S_OK;
  642. }
  643. HRESULT STDMETHODCALLTYPE CRepository::FlushCache(
  644. DWORD dwFlags
  645. )
  646. {
  647. return S_OK;
  648. }
  649. HRESULT STDMETHODCALLTYPE CRepository::GetStatistics(
  650. DWORD dwParameter,
  651. DWORD *pdwValue
  652. )
  653. {
  654. return S_OK;
  655. }
  656. HRESULT STDMETHODCALLTYPE CRepository::GetRepositoryVersions(DWORD *pdwOldVersion,
  657. DWORD *pdwCurrentVersion)
  658. {
  659. *pdwOldVersion = g_dwOldRepositoryVersion;
  660. *pdwCurrentVersion = g_dwCurrentRepositoryVersion;
  661. return S_OK;
  662. }
  663. HRESULT CRepository::GetNamespaceHandle(LPCWSTR wszNamespaceName,
  664. RELEASE_ME CNamespaceHandle** ppHandle)
  665. {
  666. HRESULT hres;
  667. //
  668. // No validation --- that would be too hard. Just create a handle and
  669. // return
  670. //
  671. CNamespaceHandle* pNewHandle = new CNamespaceHandle(m_pControl, this);
  672. if (pNewHandle == NULL)
  673. return WBEM_E_OUT_OF_MEMORY;
  674. pNewHandle->AddRef();
  675. CReleaseMe rm1(pNewHandle);
  676. hres = pNewHandle->Initialize(wszNamespaceName);
  677. if(FAILED(hres))
  678. return hres;
  679. *ppHandle = pNewHandle;
  680. pNewHandle->AddRef();
  681. return S_OK;
  682. }
  683. HRESULT CRepository::Backup(LPCWSTR wszBackupFile, long lFlags)
  684. {
  685. HRESULT hRes = WBEM_S_NO_ERROR;
  686. // params have already been verified by the calling method (CWbemBackupRestore::DoBackup),
  687. // but do it again just in case things change and this is no longer the case
  688. if (NULL == wszBackupFile || (lFlags != 0))
  689. return WBEM_E_INVALID_PARAMETER;
  690. //We need to lock the database so no one writes to it while we are backing it up
  691. CAutoReadLock lock(&g_readWriteLock);
  692. if (g_bShuttingDown)
  693. return WBEM_E_SHUTTING_DOWN;
  694. //We need to wait for the stage write to flush...
  695. DWORD dwCount = 0;
  696. long lFlushStatus = 0;
  697. while (!g_Glob.GetFileCache()->IsFullyFlushed())
  698. {
  699. if (g_Glob.GetFileCache()->GetFlushFailure(&lFlushStatus))
  700. {
  701. return lFlushStatus;
  702. }
  703. Sleep(100);
  704. if (++dwCount ==100000)
  705. {
  706. //We have a real problem here! We need to fail the operation.
  707. hRes = WBEM_E_TIMED_OUT;
  708. break;
  709. }
  710. }
  711. if (SUCCEEDED(hRes))
  712. {
  713. CRepositoryPackager packager;
  714. hRes = packager.PackageRepository(wszBackupFile);
  715. }
  716. return hRes;
  717. }
  718. HRESULT CRepository::Restore(LPCWSTR wszBackupFile, long lFlags)
  719. {
  720. return WBEM_E_NOT_SUPPORTED;
  721. }
  722. HRESULT CRepository::LockRepository()
  723. {
  724. HRESULT hRes = WBEM_S_NO_ERROR;
  725. //Lock the database so no one writes to it
  726. g_readWriteLock.ReadLock();
  727. if (g_bShuttingDown)
  728. {
  729. g_readWriteLock.ReadUnlock();
  730. return WBEM_E_SHUTTING_DOWN;
  731. }
  732. //We need to wait for the stage write to flush...
  733. DWORD dwCount = 0;
  734. long lFlushStatus = 0;
  735. while (!g_Glob.GetFileCache()->IsFullyFlushed())
  736. {
  737. if (g_Glob.GetFileCache()->GetFlushFailure(&lFlushStatus))
  738. {
  739. g_readWriteLock.ReadUnlock();
  740. return lFlushStatus;
  741. }
  742. Sleep(100);
  743. if (++dwCount == 100000)
  744. {
  745. //We have a real problem here! We need to fail the operation.
  746. hRes = WBEM_E_TIMED_OUT;
  747. g_readWriteLock.ReadUnlock();
  748. break;
  749. }
  750. }
  751. return hRes;
  752. }
  753. HRESULT CRepository::UnlockRepository()
  754. {
  755. g_readWriteLock.ReadUnlock();
  756. return WBEM_S_NO_ERROR;
  757. }
  758. //
  759. //
  760. //
  761. //
  762. //////////////////////////////////////////////////////////////////////
  763. CGlobals g_Glob;
  764. HRESULT
  765. CGlobals::Initialize()
  766. {
  767. CInCritSec ics(&m_cs);
  768. if (m_bInit)
  769. return S_OK;
  770. HRESULT hRes;
  771. hRes = CoCreateInstance(CLSID_IWmiCoreServices, NULL,
  772. CLSCTX_INPROC_SERVER, IID__IWmiCoreServices,
  773. (void**)&m_pCoreServices);
  774. if (SUCCEEDED(hRes))
  775. {
  776. hRes = m_ForestCache.Initialize();
  777. if (SUCCEEDED(hRes))
  778. {
  779. m_bInit = TRUE;
  780. }
  781. else
  782. {
  783. m_pCoreServices->Release();
  784. m_pCoreServices = NULL;
  785. }
  786. }
  787. return hRes;
  788. }
  789. HRESULT
  790. CGlobals::Deinitialize()
  791. {
  792. CInCritSec ics(&m_cs);
  793. if (!m_bInit)
  794. return S_OK;
  795. HRESULT hRes;
  796. m_pCoreServices->Release();
  797. m_pCoreServices = NULL;
  798. hRes = m_ForestCache.Deinitialize();
  799. m_bInit = FALSE;
  800. return hRes;
  801. }
  802. _IWmiCoreServices *
  803. CGlobals::GetCoreSvcs()
  804. {
  805. if (m_pCoreServices)
  806. {
  807. m_pCoreServices->AddRef();
  808. }
  809. return m_pCoreServices;
  810. }
  811. CForestCache *
  812. CGlobals::GetForestCache()
  813. {
  814. return &m_ForestCache;
  815. }
  816. CFileCache *
  817. CGlobals::GetFileCache()
  818. {
  819. return &m_FileCache;
  820. }