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

2035 lines
58 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. //***************************************************************************
  8. //
  9. // CREP.CPP
  10. //
  11. // Wrappers for repository drivers
  12. //
  13. // raymcc 27-Apr-00 WMI Repository init & mapping layer
  14. //
  15. //***************************************************************************
  16. #include "precomp.h"
  17. #include <wbemcore.h>
  18. #include <oahelp.inl>
  19. #include <unk.h>
  20. extern IClassFactory* g_pQueryFact;
  21. // ESE only.
  22. // =========
  23. IWmiDbController *CRepository::m_pEseController = 0;
  24. IWmiDbSession *CRepository::m_pEseSession = 0;
  25. IWmiDbHandle *CRepository::m_pEseRoot = 0;
  26. //
  27. //
  28. //
  29. /////////////////////////////////////////////////////////////////
  30. class CNamespaceListSink : public CUnkBase<IWbemObjectSink, &IID_IWbemObjectSink>
  31. {
  32. CWStringArray &m_aNamespaceList;
  33. public:
  34. CNamespaceListSink(CWStringArray &aNamespaceList)
  35. : m_aNamespaceList(aNamespaceList)
  36. {
  37. }
  38. ~CNamespaceListSink()
  39. {
  40. }
  41. STDMETHOD(Indicate)(long lNumObjects, IWbemClassObject** apObjects)
  42. {
  43. HRESULT hRes;
  44. for (int i = 0; i != lNumObjects; i++)
  45. {
  46. if (apObjects[i] != NULL)
  47. {
  48. _IWmiObject *pInst = NULL;
  49. hRes = apObjects[i]->QueryInterface(IID__IWmiObject, (void**)&pInst);
  50. if (FAILED(hRes))
  51. return hRes;
  52. CReleaseMe rm(pInst);
  53. BSTR strKey = NULL;
  54. hRes = pInst->GetKeyString(0, &strKey);
  55. if(FAILED(hRes))
  56. return hRes;
  57. CSysFreeMe sfm(strKey);
  58. if (m_aNamespaceList.Add(strKey) != CWStringArray::no_error)
  59. return WBEM_E_OUT_OF_MEMORY;
  60. }
  61. }
  62. return WBEM_S_NO_ERROR;
  63. }
  64. STDMETHOD(SetStatus)(long lFlags, HRESULT hresResult, BSTR, IWbemClassObject*)
  65. {
  66. return WBEM_S_NO_ERROR;
  67. }
  68. };
  69. //***************************************************************************
  70. //
  71. // CRepository::Init
  72. //
  73. //***************************************************************************
  74. HRESULT CRepository::Init()
  75. {
  76. HRESULT hRes;
  77. IWmiDbController *pController = 0;
  78. WMIDB_LOGON_TEMPLATE *pTemplate = 0;
  79. IWmiDbSession *pSession= 0;
  80. IWmiDbHandle *pRoot = 0;
  81. // Retrieve the CLSID of the default driver.
  82. // =========================================
  83. CLSID clsid;
  84. hRes = ConfigMgr::GetDefaultRepDriverClsId(clsid);
  85. if (FAILED(hRes))
  86. return hRes;
  87. hRes = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
  88. IID_IWmiDbController, (void **)&pController);
  89. if (FAILED(hRes))
  90. return hRes;
  91. CReleaseMe _1(pController);
  92. hRes = pController->GetLogonTemplate(0x409, 0, &pTemplate);
  93. if (FAILED(hRes))
  94. return hRes;
  95. //
  96. // Commenting out code since its not used for its intended 'purposes' anymore. Provides
  97. // an excellent opportunity to pass the TlsIndex of the securityFlag to the
  98. // repository though.
  99. WMIDB_LOGON_PARAMETER LogonParam ;
  100. V_VT (&(pTemplate->pParm->Value)) = VT_I4 ;
  101. V_I4 (&(pTemplate->pParm->Value)) = CCoreQueue::GetSecFlagTlsIndex ( ) ;
  102. //
  103. //for (DWORD i = 0; i < pTemplate->dwArraySize; i++)
  104. //{
  105. // if (!wbem_wcsicmp(pTemplate->pParm[i].strParmDisplayName, L"Server"))
  106. // {
  107. // pTemplate->pParm[i].Value.bstrVal = 0;
  108. // pTemplate->pParm[i].Value.vt = VT_BSTR;
  109. // }
  110. // else if (!wbem_wcsicmp(pTemplate->pParm[i].strParmDisplayName, L"Database"))
  111. // {
  112. // WString sDir = ConfigMgr::GetWorkingDir();
  113. // sDir += "\\repository\\wmi.edb";
  114. // pTemplate->pParm[i].Value.bstrVal = SysAllocString(LPWSTR(sDir));
  115. // pTemplate->pParm[i].Value.vt = VT_BSTR;
  116. // }
  117. // else if (!wbem_wcsicmp(pTemplate->pParm[i].strParmDisplayName, L"UserID"))
  118. // {
  119. // pTemplate->pParm[i].Value.bstrVal = SysAllocString(L"Admin");
  120. // pTemplate->pParm[i].Value.vt = VT_BSTR;
  121. // }
  122. // else if (!wbem_wcsicmp(pTemplate->pParm[i].strParmDisplayName, L"Password"))
  123. // {
  124. // pTemplate->pParm[i].Value.bstrVal = SysAllocString(L"");
  125. // pTemplate->pParm[i].Value.vt = VT_BSTR;
  126. // }
  127. //}
  128. // Logon to Jet.
  129. // =============
  130. hRes = pController->Logon(pTemplate, 0, WMIDB_HANDLE_TYPE_VERSIONED, &pSession, &pRoot);
  131. if (SUCCEEDED(hRes))
  132. {
  133. m_pEseSession = pSession;
  134. m_pEseRoot = pRoot; // Refcount is ok
  135. }
  136. pController->FreeLogonTemplate(&pTemplate);
  137. if (SUCCEEDED(hRes))
  138. {
  139. m_pEseController = pController;
  140. m_pEseController->AddRef();
  141. }
  142. // Ensure ROOT and ROOT\DEFAULT are there.
  143. // =======================================
  144. if (SUCCEEDED(hRes))
  145. hRes = EnsureDefault(); // SEC:REVIEWED 2002-03-22 : Needs exception handler
  146. if (SUCCEEDED(hRes))
  147. hRes = UpgradeSystemClasses(); // SEC:REVIEWED 2002-03-22 : Needs exception handler
  148. if (SUCCEEDED(hRes))
  149. {
  150. DWORD dwMaxSize;
  151. HKEY hKey;
  152. long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  153. L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
  154. 0, KEY_READ | KEY_WRITE, &hKey);
  155. if(lRes)
  156. return lRes;
  157. CRegCloseMe cm(hKey);
  158. DWORD dwLen = sizeof(DWORD);
  159. lRes = RegQueryValueExW(hKey, L"Max Class Cache Size", NULL, NULL,
  160. (LPBYTE)&dwMaxSize, &dwLen);
  161. if(lRes != ERROR_SUCCESS)
  162. {
  163. dwMaxSize = 5000000;
  164. lRes = RegSetValueExW(hKey, L"Max Class Cache Size", 0, REG_DWORD,
  165. (LPBYTE)&dwMaxSize, sizeof(DWORD));
  166. }
  167. m_pEseController->SetCacheValue(dwMaxSize);
  168. }
  169. return hRes;
  170. }
  171. //***************************************************************************
  172. //
  173. //***************************************************************************
  174. //
  175. HRESULT CRepository::EnsureDefault()
  176. {
  177. HRESULT hRes;
  178. IWmiDbSession *pSession = NULL;
  179. IWmiDbSessionEx *pSessionEx = NULL;
  180. IWmiDbHandle *pRootNs = 0, *pRootDefaultNs = 0, *pRootSecurityNs = 0;
  181. //Create a new session...
  182. hRes = CRepository::GetNewSession(&pSession);
  183. if (FAILED(hRes))
  184. return hRes;
  185. //Get an EX version that supports transactioning...
  186. pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pSessionEx);
  187. if (pSessionEx)
  188. {
  189. pSession->Release();
  190. pSession = pSessionEx;
  191. }
  192. CReleaseMe relMe1(pSession);
  193. //If we have transactionable session, use it!
  194. if (pSessionEx)
  195. {
  196. hRes = pSessionEx->BeginWriteTransaction(0);
  197. if (FAILED(hRes))
  198. {
  199. return hRes;
  200. }
  201. }
  202. try
  203. {
  204. //First we work on the ROOT namespace
  205. //-----------------------------------
  206. hRes = OpenEseNs(pSession, L"ROOT", &pRootNs);
  207. if (hRes == WBEM_E_NOT_FOUND)
  208. {
  209. //Create as it does not exist...
  210. hRes = CreateEseNs(pSession, L"ROOT", &pRootNs);
  211. }
  212. //Unfortunately, root always seems to have been created, so cannot actually optimise this one!
  213. if (SUCCEEDED(hRes))
  214. {
  215. //Create objects that only reside in the root namespace
  216. hRes = EnsureNsSystemRootObjects(pSession, pRootNs, NULL, NULL);
  217. }
  218. if (SUCCEEDED(hRes))
  219. {
  220. //Create generic instances that exist in all namespaces
  221. hRes = EnsureNsSystemInstances(pSession, pRootNs, NULL, NULL);
  222. }
  223. if (hRes == WBEM_E_NOT_FOUND)
  224. {
  225. //Something bad happened! This error has a special meaning
  226. //later on, so remapping so something safer!
  227. hRes = WBEM_E_FAILED;
  228. }
  229. //Next we work on the ROOT\DEFAULT namesapce...
  230. //---------------------------------------------
  231. if (SUCCEEDED(hRes))
  232. {
  233. hRes = OpenEseNs(pSession, L"ROOT\\DEFAULT", &pRootDefaultNs);
  234. }
  235. if (hRes == WBEM_E_NOT_FOUND)
  236. {
  237. //Create the namespace as it does not exist and add all the standard
  238. //stuff that is needed in there...
  239. hRes = CreateEseNs(pSession, L"ROOT\\DEFAULT", &pRootDefaultNs);
  240. if (SUCCEEDED(hRes))
  241. {
  242. //Need to auto-recover MOFs as this point guarentees that this is
  243. //a new repository
  244. ConfigMgr::SetDefaultMofLoadingNeeded();
  245. }
  246. if (SUCCEEDED(hRes))
  247. {
  248. //Create generic instances that exist in all namespaces
  249. hRes = EnsureNsSystemInstances(pSession, pRootDefaultNs, pSession, pRootNs);
  250. }
  251. }
  252. if (hRes == WBEM_E_NOT_FOUND)
  253. {
  254. //Something bad happened! This error has a special meaning
  255. //later on, so remapping so something safer!
  256. hRes = WBEM_E_FAILED;
  257. }
  258. //Finally we work on the ROOT\SECURITY namespace
  259. //-----------------------------------------------
  260. if (SUCCEEDED(hRes))
  261. {
  262. hRes = OpenEseNs(pSession, L"ROOT\\SECURITY", &pRootSecurityNs);
  263. }
  264. if (hRes == WBEM_E_NOT_FOUND)
  265. {
  266. //The namespace is not there so create it
  267. hRes = CreateEseNs(pSession, L"ROOT\\SECURITY", &pRootSecurityNs);
  268. if (SUCCEEDED(hRes))
  269. {
  270. //Store system instances that exist in all namespaces
  271. hRes = EnsureNsSystemInstances(pSession, pRootSecurityNs, pSession, pRootNs);
  272. }
  273. if (SUCCEEDED(hRes))
  274. {
  275. //Store the security objects into the namespace. These only reside in this
  276. //namespace
  277. hRes = EnsureNsSystemSecurityObjects(pSession, pRootSecurityNs, pSession, pRootNs);
  278. }
  279. }
  280. }
  281. catch (...) // not sure about this one
  282. {
  283. ExceptionCounter c;
  284. ERRORTRACE((LOG_WBEMCORE, "Creation of empty repository caused a very critical error!\n"));
  285. hRes = WBEM_E_CRITICAL_ERROR;
  286. }
  287. if (SUCCEEDED(hRes))
  288. {
  289. //Commit the transaction
  290. if (pSessionEx)
  291. {
  292. hRes = pSessionEx->CommitTransaction(0);
  293. }
  294. }
  295. else
  296. {
  297. ERRORTRACE((LOG_WBEMCORE, "Creation of empty repository failed with error <0x%X>!\n", hRes));
  298. if (pSessionEx)
  299. pSessionEx->AbortTransaction(0);
  300. }
  301. if (pRootNs)
  302. pRootNs->Release();
  303. if (pRootDefaultNs)
  304. pRootDefaultNs->Release();
  305. if (pRootSecurityNs)
  306. pRootSecurityNs->Release();
  307. return hRes;
  308. }
  309. //***************************************************************************
  310. //
  311. //***************************************************************************
  312. //
  313. HRESULT CRepository::Shutdown(BOOL bIsSystemShutDown)
  314. {
  315. if (m_pEseRoot)
  316. {
  317. m_pEseRoot->Release();
  318. m_pEseRoot = NULL;
  319. }
  320. if (m_pEseSession)
  321. {
  322. m_pEseSession->Release();
  323. m_pEseSession = NULL;
  324. }
  325. if (m_pEseController)
  326. {
  327. m_pEseController->Shutdown(bIsSystemShutDown?WMIDB_SHUTDOWN_MACHINE_DOWN:0);
  328. m_pEseController->Release();
  329. m_pEseController = NULL;
  330. }
  331. return WBEM_S_NO_ERROR;
  332. }
  333. //***************************************************************************
  334. //
  335. //***************************************************************************
  336. // ok
  337. HRESULT CRepository::GetDefaultSession(
  338. OUT IWmiDbSession **pSession
  339. )
  340. {
  341. if (m_pEseSession == 0)
  342. return WBEM_E_CRITICAL_ERROR;
  343. *pSession = m_pEseSession;
  344. (*pSession)->AddRef();
  345. return WBEM_S_NO_ERROR;
  346. }
  347. //***************************************************************************
  348. //
  349. // CRepository::OpenNs
  350. //
  351. // ESE only
  352. //
  353. //***************************************************************************
  354. //
  355. HRESULT CRepository::OpenEseNs(
  356. IN IWmiDbSession *pSession,
  357. IN LPCWSTR pszNamespace,
  358. OUT IWmiDbHandle **pHandle
  359. )
  360. {
  361. if (pHandle == 0)
  362. return WBEM_E_INVALID_PARAMETER;
  363. if (pSession == NULL)
  364. pSession = m_pEseSession;
  365. *pHandle = 0;
  366. // Check for virtual root ns (one level up from ROOT).
  367. // ===================================================
  368. if (pszNamespace == 0)
  369. {
  370. if (m_pEseRoot == 0)
  371. return WBEM_E_CRITICAL_ERROR;
  372. *pHandle = m_pEseRoot;
  373. (*pHandle)->AddRef();
  374. return WBEM_S_NO_ERROR;
  375. }
  376. // Loop through the nested namespaces until we get to the last one.
  377. // ================================================================
  378. size_t tmpLength = wcslen(pszNamespace)+1;
  379. wchar_t* pszSource = new wchar_t[tmpLength];
  380. CVectorDeleteMe<wchar_t> vdm1(pszSource);
  381. if (pszSource == NULL)
  382. return WBEM_E_OUT_OF_MEMORY;
  383. StringCchCopyW(pszSource, tmpLength, pszNamespace);
  384. LPCWSTR pszDelimit = L"\\";
  385. LPWSTR pszTok = wcstok(LPWSTR(pszSource), pszDelimit);
  386. HRESULT hRes = 0;
  387. IWmiDbHandle *pCurrent = m_pEseRoot;
  388. IWmiDbHandle *pTmp = 0;
  389. if (pCurrent)
  390. pCurrent->AddRef();
  391. else
  392. return WBEM_E_CRITICAL_ERROR;
  393. while (pszTok)
  394. {
  395. // Current namespace is <pszTok>
  396. // =============================
  397. IWbemPath *pPath = ConfigMgr::GetNewPath();
  398. if (pPath == 0)
  399. {
  400. pCurrent->Release();
  401. return WBEM_E_OUT_OF_MEMORY;
  402. }
  403. CReleaseMe _1(pPath);
  404. WString sPath;
  405. try
  406. {
  407. sPath = "__namespace='";
  408. sPath += pszTok; // SEC:REVIEWED 2002-03-22 : Needs long-name check
  409. sPath += "'";
  410. }
  411. catch (CX_MemoryException &)
  412. {
  413. return WBEM_E_OUT_OF_MEMORY;
  414. };
  415. pPath->SetText(WBEMPATH_TREAT_SINGLE_IDENT_AS_NS | WBEMPATH_CREATE_ACCEPT_ALL , sPath);
  416. hRes = pSession->GetObject(pCurrent, pPath, 0, WMIDB_HANDLE_TYPE_COOKIE, &pTmp);
  417. pszTok = wcstok(NULL, pszDelimit); // SEC:REVIEWED 2002-03-22 : What happens if ill formed?
  418. pCurrent->Release();
  419. if (FAILED(hRes))
  420. return hRes;
  421. // If here, we got it. So either we are done, or we need to keep going.
  422. // =====================================================================
  423. if (pszTok)
  424. pCurrent = pTmp;
  425. else
  426. {
  427. // All done
  428. *pHandle = pTmp;
  429. break;
  430. }
  431. }
  432. return WBEM_S_NO_ERROR;
  433. }
  434. //***************************************************************************
  435. //
  436. //***************************************************************************
  437. // Executed; seems to work
  438. HRESULT CRepository::GetObject(
  439. IN IWmiDbSession *pSession,
  440. IN IWmiDbHandle *pNs,
  441. IN LPCWSTR pszObjectPath, // NS relative only for now
  442. IN ULONG uFlags,
  443. OUT IWbemClassObject **pObj
  444. )
  445. {
  446. HRESULT hRes;
  447. //
  448. // Check if the session supports faster interface
  449. //
  450. IWmiDbSessionEx* pEx = NULL;
  451. hRes = pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pEx);
  452. if(SUCCEEDED(hRes))
  453. {
  454. CReleaseMe rm1(pEx);
  455. hRes = pEx->GetObjectByPath(pNs, pszObjectPath, uFlags,
  456. IID_IWbemClassObject, (void**)pObj);
  457. }
  458. else
  459. {
  460. // Path to object.
  461. // ===============
  462. IWbemPath *pPath = ConfigMgr::GetNewPath();
  463. if (pPath == 0)
  464. return WBEM_E_OUT_OF_MEMORY;
  465. CReleaseMe _1(pPath);
  466. pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pszObjectPath);
  467. // Get it.
  468. // =======
  469. hRes = pSession->GetObjectDirect(pNs, pPath, uFlags, IID_IWbemClassObject, (void **)pObj);
  470. }
  471. if (FAILED(hRes))
  472. {
  473. // DEBUGTRACE((LOG_REPDRV, "Failed with 0x%X\n", hRes));
  474. return hRes;
  475. }
  476. else
  477. {
  478. #ifdef TESTONLY
  479. BSTR str = 0;
  480. (*pObj)->GetObjectText(0, &str);
  481. DEBUGTRACE((LOG_REPDRV, " GetObject() Text = \n%S\n\n", str));
  482. SysFreeString(str);
  483. #endif
  484. }
  485. return hRes;
  486. }
  487. //***************************************************************************
  488. //
  489. // Does not support nesting yet
  490. //
  491. //***************************************************************************
  492. // ok
  493. HRESULT CRepository::CreateEseNs(
  494. IN IWmiDbSession *pSession,
  495. IN LPCWSTR pszNamespace,
  496. OUT IWmiDbHandle **pHandle
  497. )
  498. {
  499. HRESULT hRes = 0;
  500. if (pszNamespace == 0 || pHandle == 0)
  501. return WBEM_E_INVALID_PARAMETER;
  502. if (pSession == NULL)
  503. {
  504. pSession = m_pEseSession;
  505. }
  506. // Loop through each namespace and try to open it. If we can
  507. // keep going. If we fail, create it at the current level and
  508. // return the handle.
  509. // ===========================================================
  510. size_t tmpLength = wcslen(pszNamespace)+1;
  511. wchar_t* pszSource = new wchar_t[tmpLength];
  512. CVectorDeleteMe<wchar_t> vdm1(pszSource);
  513. if (pszSource == NULL)
  514. return WBEM_E_OUT_OF_MEMORY;
  515. StringCchCopyW(pszSource, tmpLength, pszNamespace);
  516. LPCWSTR pszDelimit = L"\\";
  517. LPWSTR pszTok = wcstok(LPWSTR(pszSource), pszDelimit); // First ns token
  518. IWmiDbHandle *pCurrent = m_pEseRoot;
  519. IWmiDbHandle *pTmp = 0;
  520. pCurrent->AddRef();
  521. while (pszTok)
  522. {
  523. // Current namespace is <pszTok>
  524. // =============================
  525. IWbemPath *pPath = ConfigMgr::GetNewPath();
  526. if (pPath == 0)
  527. {
  528. pCurrent->Release();
  529. return WBEM_E_OUT_OF_MEMORY;
  530. }
  531. CReleaseMe _1(pPath);
  532. WString sPath = "__namespace='";
  533. sPath += pszTok;
  534. sPath += "'";
  535. pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, sPath);
  536. hRes = pSession->GetObject(pCurrent, pPath, 0, WMIDB_HANDLE_TYPE_COOKIE, &pTmp);
  537. size_t tmpLenght = wcslen(pszTok)+1;
  538. wchar_t* TmpStr = new wchar_t[tmpLenght];
  539. if (TmpStr == NULL)
  540. {
  541. pCurrent->Release();
  542. return WBEM_E_OUT_OF_MEMORY;
  543. }
  544. CVectorDeleteMe<wchar_t> vdm1(TmpStr);
  545. *TmpStr = 0;
  546. if (pszTok)
  547. StringCchCopyW(TmpStr, tmpLenght, pszTok);
  548. pszTok = wcstok(NULL, pszDelimit);
  549. if (FAILED(hRes))
  550. {
  551. // If here, we try to create the namespace.
  552. // ========================================
  553. // Get a copy of class __Namespace
  554. // ================================
  555. IWbemClassObject *pNsClass = 0;
  556. hRes = GetObject(pSession, pCurrent, L"__Namespace", 0,
  557. &pNsClass);
  558. if (FAILED(hRes))
  559. {
  560. pCurrent->Release();
  561. return hRes;
  562. }
  563. CReleaseMe _1(pNsClass);
  564. IWbemClassObject *pNs;
  565. pNsClass->SpawnInstance(0, &pNs);
  566. CReleaseMe _(pNs);
  567. CVARIANT v;
  568. v.SetStr(TmpStr);
  569. pNs->Put(L"Name", 0, &v, 0);
  570. hRes = pSession->PutObject(pCurrent, IID_IWbemClassObject, pNs, WBEM_FLAG_CREATE_ONLY, WMIDB_HANDLE_TYPE_VERSIONED, &pTmp);
  571. if (FAILED(hRes))
  572. {
  573. pCurrent->Release();
  574. return hRes;
  575. }
  576. pCurrent->Release();
  577. pCurrent = pTmp;
  578. if (pszTok)
  579. continue;
  580. *pHandle = pTmp;
  581. break;
  582. }
  583. // If here, we got it. So either we are done, or we need to keep going.
  584. // =====================================================================
  585. else if (pszTok)
  586. {
  587. pCurrent->Release();
  588. pCurrent = pTmp;
  589. }
  590. else
  591. {
  592. // All done
  593. *pHandle = pTmp;
  594. break;
  595. }
  596. }
  597. return WBEM_S_NO_ERROR;
  598. }
  599. //***************************************************************************
  600. //
  601. //***************************************************************************
  602. // Executed; seems to work
  603. HRESULT CRepository::PutObject(
  604. IN IWmiDbSession *pSession,
  605. IN IWmiDbHandle *pNs,
  606. IN REFIID riid,
  607. IN LPVOID pObj,
  608. IN DWORD dwFlags
  609. )
  610. {
  611. if (pNs == 0 || pObj == 0)
  612. return WBEM_E_INVALID_PARAMETER;
  613. if(dwFlags & WBEM_FLAG_NO_EVENTS)
  614. {
  615. dwFlags |= WMIDB_DISABLE_EVENTS;
  616. }
  617. // Mask out unrecognized flags
  618. dwFlags &= (WBEM_FLAG_OWNER_UPDATE | WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_CREATE_ONLY | WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_UPDATE_SAFE_MODE | WBEM_FLAG_UPDATE_FORCE_MODE
  619. | WBEM_FLAG_USE_SECURITY_DESCRIPTOR | WMIDB_FLAG_ADMIN_VERIFIED | WMIDB_DISABLE_EVENTS);
  620. HRESULT hRes;
  621. try
  622. {
  623. hRes = pSession->PutObject(pNs, riid, pObj, dwFlags, 0, 0);
  624. }
  625. catch(...)
  626. {
  627. ExceptionCounter c;
  628. hRes = WBEM_E_CRITICAL_ERROR;
  629. }
  630. return hRes;
  631. }
  632. //***************************************************************************
  633. //
  634. //***************************************************************************
  635. // inspected; no execution history
  636. HRESULT CRepository::ExecQuery(
  637. IN IWmiDbSession *pSession,
  638. IN IWmiDbHandle *pNs,
  639. IN LPCWSTR pszQuery,
  640. IN IWbemObjectSink *pSink,
  641. IN LONG lFlags
  642. )
  643. {
  644. HRESULT hRes = 0;
  645. IWbemQuery *pQuery = NULL;
  646. hRes = g_pQueryFact->CreateInstance(0, IID_IWbemQuery, (void **)&pQuery);
  647. if (FAILED(hRes))
  648. {
  649. pSink->SetStatus(0, WBEM_E_CRITICAL_ERROR, 0, 0);
  650. return WBEM_E_CRITICAL_ERROR;
  651. }
  652. CReleaseMe _1(pQuery);
  653. hRes = pQuery->Parse(L"SQL", pszQuery, 0);
  654. if (FAILED(hRes))
  655. {
  656. pSink->SetStatus(0, WBEM_E_INVALID_QUERY, 0, 0);
  657. return WBEM_E_INVALID_QUERY;
  658. }
  659. // Now, execute the query.
  660. // =======================
  661. IWmiDbIterator *pIterator = NULL;
  662. try
  663. {
  664. hRes = pSession->ExecQuery(pNs, pQuery, lFlags, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pIterator);
  665. }
  666. catch(...)
  667. {
  668. ExceptionCounter c;
  669. hRes = WBEM_E_CRITICAL_ERROR;
  670. }
  671. // If this is a "delete" query, there
  672. // will be no iterator.
  673. // ==================================
  674. if (FAILED(hRes) || !pIterator)
  675. {
  676. pSink->SetStatus(0, hRes, 0, 0);
  677. return hRes;
  678. }
  679. // If here, there are results, I guess.
  680. // ====================================
  681. REFIID riid = IID_IWbemClassObject;
  682. DWORD dwObjects = 0;
  683. // Convert current thread to a fiber
  684. // =================================
  685. // First, uncovert the thread to prevent a leak if we are already
  686. // converted. There is no way of checking, sadly.
  687. void* pFiber = NULL;
  688. _TEB *pTeb = NtCurrentTeb();
  689. BOOL bIsThisThreadAlreadyAFiber = (pTeb->HasFiberData != 0);
  690. if (!bIsThisThreadAlreadyAFiber)
  691. pFiber = ConvertThreadToFiber(NULL);
  692. else
  693. pFiber = GetCurrentFiber();
  694. if(pFiber == NULL)
  695. {
  696. if (pIterator)
  697. pIterator->Release();
  698. pSink->SetStatus(0, WBEM_E_OUT_OF_MEMORY, 0, 0);
  699. return WBEM_E_OUT_OF_MEMORY;
  700. }
  701. // Extract everything from the iterator
  702. // ====================================
  703. while (1)
  704. {
  705. IWbemClassObject *pObj = 0;
  706. DWORD dwReturned = 0;
  707. hRes = pIterator->NextBatch(
  708. 1, // one at a time for now
  709. 5, // Timeout seconds(or milliseconds? who knows...)
  710. 0, // Flags
  711. WMIDB_HANDLE_TYPE_COOKIE,
  712. riid,
  713. pFiber,
  714. &dwReturned,
  715. (LPVOID *) &pObj
  716. );
  717. if (dwReturned == 0 || pObj == 0 || FAILED(hRes))
  718. break;
  719. dwObjects += dwReturned;
  720. hRes = pSink->Indicate(1, &pObj);
  721. pObj->Release();
  722. if (FAILED(hRes)) // Allow an early cancellation
  723. break;
  724. }
  725. if (pIterator)
  726. {
  727. pIterator->Cancel(hRes, pFiber);
  728. pIterator->Release();
  729. }
  730. if (!bIsThisThreadAlreadyAFiber)
  731. ConvertFiberToThread();
  732. if (SUCCEEDED(hRes))
  733. hRes = WBEM_S_NO_ERROR;
  734. hRes = pSink->SetStatus(0, hRes, 0, 0);
  735. return hRes;
  736. }
  737. //***************************************************************************
  738. //
  739. //***************************************************************************
  740. // inspected; no execution history
  741. HRESULT CRepository::QueryClasses(
  742. IN IWmiDbSession *pSession,
  743. IN IWmiDbHandle *pNs,
  744. IN ULONG uFlags, // WBEM_FLAG_DEEP = 0, WBEM_FLAG_SHALLOW = 1,
  745. IN LPCWSTR pszSuperclass,
  746. IN IWbemObjectSink *pSink
  747. )
  748. {
  749. HRESULT hRes;
  750. // Build the query required for simple class operations.
  751. // =====================================================
  752. WString sQuery = L"select * from meta_class";
  753. if (pszSuperclass)
  754. {
  755. if (uFlags & WBEM_FLAG_SHALLOW)
  756. {
  757. sQuery += " where ";
  758. sQuery += " __SuperClass = '";
  759. sQuery += pszSuperclass;
  760. sQuery += "'";
  761. }
  762. else
  763. {
  764. if (wcslen(pszSuperclass) > 0)
  765. {
  766. sQuery += " where ";
  767. sQuery += "__this isa '";
  768. sQuery += pszSuperclass;
  769. sQuery += "'";
  770. sQuery += " and __class <> '";
  771. sQuery += pszSuperclass;
  772. sQuery += "'";
  773. }
  774. }
  775. }
  776. // Ship it to the more general query function.
  777. // ===========================================
  778. hRes = CRepository::ExecQuery(pSession, pNs, sQuery, pSink, uFlags);
  779. return hRes;
  780. }
  781. //***************************************************************************
  782. //
  783. //***************************************************************************
  784. // inspected; no execution history
  785. HRESULT CRepository::DeleteObject(
  786. IN IWmiDbSession *pSession,
  787. IN IWmiDbHandle *pNs,
  788. IN REFIID riid,
  789. IN LPVOID pObj,
  790. IN DWORD dwFlags
  791. )
  792. {
  793. return pSession->DeleteObject(pNs, dwFlags, riid, pObj);
  794. }
  795. //***************************************************************************
  796. //
  797. //***************************************************************************
  798. HRESULT CRepository::DeleteByPath(
  799. IN IWmiDbSession *pSession,
  800. IN IWmiDbHandle *pNs,
  801. IN LPCWSTR pszPath,
  802. IN DWORD uFlags
  803. )
  804. {
  805. HRESULT hRes;
  806. if(uFlags & WBEM_FLAG_NO_EVENTS)
  807. {
  808. uFlags |= WMIDB_DISABLE_EVENTS;
  809. }
  810. //
  811. // Check if the session supports faster interface
  812. //
  813. IWmiDbSessionEx* pEx = NULL;
  814. hRes = pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pEx);
  815. if(SUCCEEDED(hRes))
  816. {
  817. CReleaseMe rm1(pEx);
  818. hRes = pEx->DeleteObjectByPath(pNs, pszPath, uFlags);
  819. }
  820. else
  821. {
  822. IWmiDbHandle *pHandle = NULL;
  823. // Path to object.
  824. // ===============
  825. IWbemPath *pPath = ConfigMgr::GetNewPath();
  826. if (pPath == 0)
  827. return WBEM_E_OUT_OF_MEMORY;
  828. CReleaseMe _1(pPath);
  829. pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pszPath);
  830. hRes = pSession->GetObject(pNs, pPath, 0, WMIDB_HANDLE_TYPE_COOKIE|WMIDB_HANDLE_TYPE_EXCLUSIVE, &pHandle);
  831. if (FAILED(hRes))
  832. return hRes;
  833. hRes = DeleteObject(pSession, pNs, IID_IWmiDbHandle, pHandle, uFlags);
  834. pHandle->Release();
  835. }
  836. return hRes;
  837. }
  838. //***************************************************************************
  839. //
  840. //***************************************************************************
  841. // visually ok
  842. HRESULT CRepository::InheritsFrom(
  843. IN IWmiDbSession *pSession,
  844. IN IWmiDbHandle *pNs,
  845. IN LPCWSTR pszSuperclass,
  846. IN LPCWSTR pszSubclass
  847. )
  848. {
  849. IWbemClassObject *pObj = 0;
  850. HRESULT hRes = GetObject(pSession, pNs, pszSubclass, 0, &pObj);
  851. if (FAILED(hRes))
  852. return hRes;
  853. CReleaseMe _(pObj);
  854. hRes = pObj->InheritsFrom(pszSuperclass);
  855. return hRes;
  856. }
  857. //***************************************************************************
  858. //
  859. //***************************************************************************
  860. //
  861. HRESULT CRepository::GetRefClasses(
  862. IN IWmiDbSession *pSession,
  863. IN IWmiDbHandle *pNs,
  864. IN LPCWSTR pszClass,
  865. IN BOOL bIncludeSubclasses,
  866. OUT CWStringArray &aClasses
  867. )
  868. {
  869. WString sQuery = "references of {";
  870. sQuery +=pszClass;
  871. sQuery += "}";
  872. CSynchronousSink* pRefClassSink = CSynchronousSink::Create();
  873. if (pRefClassSink == NULL)
  874. return WBEM_E_OUT_OF_MEMORY;
  875. pRefClassSink->AddRef();
  876. CReleaseMe _1(pRefClassSink);
  877. HRESULT hRes = CRepository::ExecQuery(pSession, pNs, sQuery, pRefClassSink, 0);
  878. if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND)
  879. return WBEM_E_CRITICAL_ERROR;
  880. pRefClassSink->GetStatus(&hRes, NULL, NULL);
  881. CRefedPointerArray<IWbemClassObject>& raObjects = pRefClassSink->GetObjects();
  882. for (int i = 0; i < raObjects.GetSize(); i++)
  883. {
  884. IWbemClassObject *pClsDef = (IWbemClassObject *) raObjects[i];
  885. CVARIANT vGenus;
  886. hRes = pClsDef->Get(L"__GENUS", 0, &vGenus, 0, 0);
  887. if (FAILED(hRes))
  888. return hRes;
  889. if(V_VT(&vGenus) == VT_I4 && V_I4(&vGenus) == 1)
  890. {
  891. CVARIANT v;
  892. if(SUCCEEDED(pClsDef->Get(L"__CLASS", 0, &v, 0, 0)) && VT_BSTR == V_VT(&v))
  893. {
  894. if (CFlexArray::no_error != aClasses.Add(v.GetStr()))
  895. {
  896. // ???
  897. }
  898. }
  899. }
  900. }
  901. return WBEM_S_NO_ERROR;
  902. }
  903. //***************************************************************************
  904. //
  905. //***************************************************************************
  906. //
  907. HRESULT CRepository::GetInstanceRefs(
  908. IN IWmiDbSession *pSession,
  909. IN IWmiDbHandle *pNs,
  910. IN LPCWSTR pszTargetObject,
  911. IN IWbemObjectSink *pSink
  912. )
  913. {
  914. WString sQuery = "references of {";
  915. sQuery += pszTargetObject;
  916. sQuery += "}";
  917. HRESULT hRes = ExecQuery(pSession, pNs, sQuery, pSink, 0);
  918. return hRes;
  919. }
  920. //***************************************************************************
  921. //
  922. //***************************************************************************
  923. //
  924. HRESULT CRepository::GetClassesWithRefs(
  925. IN IWmiDbSession *pSession,
  926. IN IWmiDbHandle *pNs,
  927. IN IWbemObjectSink *pSink
  928. )
  929. {
  930. // TBD: Jet Blue
  931. return WBEM_S_NO_ERROR;
  932. }
  933. //***************************************************************************
  934. //
  935. // CRepository::BuildClassHierarchy
  936. //
  937. // Notes:
  938. // Builds a decorated class hierarchy tree. Doesn't use dyn classes yet.
  939. //
  940. // <pNs>
  941. // The namespace to use for classes.
  942. //
  943. // <pBaseClassName>
  944. // May not be null.
  945. //
  946. // <lFlags>
  947. // Not used yet.
  948. //
  949. // <pDynasty>
  950. // Receives the class dynasty tree.
  951. //
  952. // Verification:
  953. // (a) Verifies that pBaseClassName is a class which has a key or inherits one.
  954. //
  955. //******************************************************************************
  956. //
  957. HRESULT CRepository::BuildClassHierarchy(
  958. IN IWmiDbSession *pSession,
  959. IN IWmiDbHandle *pNs,
  960. IN LPCWSTR pBaseClassName,
  961. IN LONG lFlags,
  962. OUT wmilib::auto_ptr<CDynasty> & pDynasty
  963. )
  964. {
  965. if (pNs == 0 || pBaseClassName == 0 )
  966. return WBEM_E_INVALID_PARAMETER;
  967. // First, execute a schema query for all the classes in the dynasty.
  968. // We verify that the base as a key, or else it is an error.
  969. //
  970. // TBD: Dynamic classes are not merged in yet
  971. //
  972. // ================================================================
  973. WString sQuery = "select * from meta_class where __this isa '";
  974. sQuery += pBaseClassName;
  975. sQuery += "'";
  976. CSynchronousSink* pRefClassSink = CSynchronousSink::Create();
  977. if (pRefClassSink == NULL) return WBEM_E_OUT_OF_MEMORY;
  978. pRefClassSink->AddRef();
  979. CReleaseMe _1(pRefClassSink);
  980. HRESULT hRes = CRepository::ExecQuery(pSession, pNs, sQuery, pRefClassSink, 0);
  981. if (FAILED(hRes)) return hRes;
  982. pRefClassSink->Block();
  983. pRefClassSink->GetStatus(&hRes, NULL, NULL);
  984. CRefedPointerArray<IWbemClassObject>& raObjects = pRefClassSink->GetObjects();
  985. // Find root class amongst all those relatives.
  986. // ============================================
  987. CFlexArray aClasses;
  988. IWbemClassObject *pRoot = 0;
  989. for (int i = 0; i < raObjects.GetSize(); i++)
  990. {
  991. IWbemClassObject *pClsDef = (IWbemClassObject *) raObjects[i];
  992. _variant_t v;
  993. hRes = pClsDef->Get(L"__CLASS", 0, &v, 0, 0);
  994. if (FAILED(hRes)) return hRes;
  995. if (VT_BSTR != V_VT(&v)) return WBEM_E_INVALID_OBJECT;
  996. if (0 == wbem_wcsicmp(V_BSTR(&v), pBaseClassName))
  997. pRoot = pClsDef;
  998. else
  999. {
  1000. if (CFlexArray::no_error != aClasses.Add(pClsDef))
  1001. return WBEM_E_OUT_OF_MEMORY;
  1002. }
  1003. }
  1004. if (pRoot == 0) // Did we find it?
  1005. return WBEM_E_NOT_FOUND;
  1006. // Algorithm:
  1007. // Add root class first, enqueue the ptr.
  1008. //
  1009. // (a) Dequeue ptr into pCurrentClass
  1010. // (b) Find all classes which have pCurrentClass as the parent
  1011. // For each, create a CDynasty, add it to the current dynasty
  1012. // and enqueue each. Remove enqueued class from array.
  1013. // (c) Goto (a)
  1014. CFlexQueue Q;
  1015. pDynasty.reset( CDynasty::Create(pRoot));
  1016. if (NULL == pDynasty.get()) return WBEM_E_OUT_OF_MEMORY;
  1017. Q.Enqueue(pDynasty.get());
  1018. while (aClasses.Size())
  1019. {
  1020. CDynasty *pCurrent = (CDynasty *) Q.Dequeue();
  1021. if (pCurrent == 0)
  1022. break;
  1023. _variant_t vClassName;
  1024. hRes = pCurrent->m_pClassObj->Get(L"__CLASS", 0, &vClassName, 0, 0);
  1025. if (FAILED(hRes)) return hRes;
  1026. if (VT_BSTR != V_VT(&vClassName)) return WBEM_E_INVALID_OBJECT;
  1027. for (int i = 0; i < aClasses.Size(); i++)
  1028. {
  1029. IWbemClassObject *pCandidate = (IWbemClassObject *) aClasses[i];
  1030. _variant_t vSuperClass;
  1031. hRes = pCandidate->Get(L"__SUPERCLASS", 0, &vSuperClass, 0, 0);
  1032. if (FAILED(hRes)) return hRes;
  1033. //if (VT_BSTR != V_VT(&vClassName)) return WBEM_E_INVALID_PROPERTY_TYPE;
  1034. if (vSuperClass.vt == VT_BSTR && wbem_wcsicmp(V_BSTR(&vSuperClass), V_BSTR(&vClassName)) == 0)
  1035. {
  1036. wmilib::auto_ptr<CDynasty> pNewChild( CDynasty::Create(pCandidate));
  1037. if (pNewChild.get() == NULL) return WBEM_E_OUT_OF_MEMORY;
  1038. pCurrent->AddChild(pNewChild.get()); // throw
  1039. Q.Enqueue(pNewChild.get());
  1040. pNewChild.release();
  1041. aClasses.RemoveAt(i);
  1042. i--;
  1043. }
  1044. }
  1045. }
  1046. return WBEM_S_NO_ERROR;
  1047. }
  1048. //***************************************************************************
  1049. //
  1050. //***************************************************************************
  1051. //
  1052. HRESULT CRepository::FindKeyRoot(
  1053. IN IWmiDbSession *pSession,
  1054. IN IWmiDbHandle *pNs,
  1055. IN LPCWSTR wszClassName,
  1056. OUT IWbemClassObject** ppKeyRootClass
  1057. )
  1058. {
  1059. if (pNs == 0 || wszClassName == 0 || ppKeyRootClass == 0)
  1060. return WBEM_E_INVALID_PARAMETER;
  1061. // Work through derivation until we find the class with the key.
  1062. // =============================================================
  1063. *ppKeyRootClass = 0;
  1064. HRESULT hRes;
  1065. IWbemClassObject* pLastClass = NULL;
  1066. WString sNextClass = wszClassName; // throw
  1067. while (1)
  1068. {
  1069. IWbemClassObject *pNextClass = 0;
  1070. hRes = CRepository::GetObject(pSession, pNs, sNextClass, 0, &pNextClass);
  1071. if (FAILED(hRes)) break;
  1072. CReleaseMe rm(pNextClass);
  1073. CVARIANT v;
  1074. hRes = pNextClass->Get(L"__SUPERCLASS", 0, &v, 0, 0);
  1075. if ( FAILED(hRes) ) break;
  1076. if ( V_VT(&v) == VT_NULL )
  1077. {
  1078. sNextClass.Empty();
  1079. }
  1080. else
  1081. {
  1082. sNextClass = v.GetStr(); // throw
  1083. }
  1084. BSTR strProp = 0;
  1085. LONG lFlavor = 0;
  1086. pNextClass->BeginEnumeration(WBEM_FLAG_KEYS_ONLY);
  1087. hRes = pNextClass->Next(0, &strProp, 0, 0, &lFlavor);
  1088. // WBEM_S_NO_ERROR means we got a property that was defined as a key
  1089. if (hRes == WBEM_S_NO_ERROR)
  1090. {
  1091. SysFreeString(strProp);
  1092. if ( pLastClass ) pLastClass->Release();
  1093. pLastClass = pNextClass;
  1094. pLastClass->AddRef();
  1095. }
  1096. else if ( hRes == WBEM_S_NO_MORE_DATA )
  1097. {
  1098. // If we don't have a last class, then we didn't find anything. Otherwise,
  1099. // since we found no key's here, the last class was the one that defined the
  1100. // keys
  1101. if ( pLastClass )
  1102. {
  1103. *ppKeyRootClass = pLastClass;
  1104. return WBEM_S_NO_ERROR;
  1105. }
  1106. // outta here
  1107. break;
  1108. }
  1109. else
  1110. {
  1111. // Otherwise something is just plain wrong
  1112. break;
  1113. }
  1114. }
  1115. return WBEM_E_NOT_FOUND;
  1116. }
  1117. //***************************************************************************
  1118. //
  1119. //***************************************************************************
  1120. // visually ok
  1121. HRESULT CRepository::TableScanQuery(
  1122. IN IWmiDbSession *pSession,
  1123. IN IWmiDbHandle *pNs,
  1124. IN LPCWSTR pszClassName,
  1125. IN QL_LEVEL_1_RPN_EXPRESSION *pExp, // NOT USED
  1126. IN DWORD dwFlags,
  1127. IN IWbemObjectSink *pSink
  1128. )
  1129. {
  1130. WString sQuery = "select * from ";
  1131. sQuery += pszClassName;
  1132. HRESULT hRes = CRepository::ExecQuery(pSession, pNs, sQuery, pSink, 0);
  1133. return hRes;
  1134. }
  1135. //***************************************************************************
  1136. //
  1137. //***************************************************************************
  1138. //
  1139. HRESULT CRepository::InitDriver(
  1140. IN ULONG uFlags,
  1141. IN IWbemClassObject *pMappedNs,
  1142. OUT IWmiDbController **pResultController,
  1143. OUT IWmiDbSession **pResultRootSession,
  1144. OUT IWmiDbHandle **pResultVirtualRoot
  1145. )
  1146. {
  1147. return E_NOTIMPL;
  1148. }
  1149. //***************************************************************************
  1150. //
  1151. //***************************************************************************
  1152. //
  1153. HRESULT CRepository::EnsureNsSystemInstances(
  1154. IN IWmiDbSession *pSession,
  1155. IN IWmiDbHandle *pNs,
  1156. IN IWmiDbSession *pParentSession,
  1157. IN IWmiDbHandle *pParentNs
  1158. )
  1159. {
  1160. HRESULT hRes;
  1161. // Do a get and see if __WmiMappedDriverNamespace is there.
  1162. // ========================================================
  1163. IWbemClassObject *pTestObj = 0;
  1164. hRes = GetObject(pSession, pNs, L"__systemsecurity=@", 0, &pTestObj);
  1165. if (SUCCEEDED(hRes))
  1166. {
  1167. pTestObj->Release();
  1168. return WBEM_S_NO_ERROR;
  1169. }
  1170. // If here, it's a new namespace that has to be populated with system classes.
  1171. // ===========================================================================
  1172. CCoreServices *pSvc = CCoreServices::CreateInstance();
  1173. if (pSvc == NULL)
  1174. return WBEM_E_OUT_OF_MEMORY;
  1175. _IWmiObject *Objects[256];
  1176. ULONG uSize = 256;
  1177. hRes = pSvc->GetSystemObjects(GET_SYSTEM_STD_INSTANCES, &uSize, Objects);
  1178. if (SUCCEEDED(hRes))
  1179. {
  1180. for (int i = 0; i < uSize; i++)
  1181. {
  1182. IWbemClassObject *pObj;
  1183. if (SUCCEEDED(hRes))
  1184. {
  1185. hRes = Objects[i]->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pObj);
  1186. if (SUCCEEDED(hRes))
  1187. {
  1188. AutoRevertSecTlsFlag secFlag ( (LPVOID) 0 ) ;
  1189. hRes = PutObject(pSession, pNs, IID_IWbemClassObject, pObj, WMIDB_DISABLE_EVENTS);
  1190. pObj->Release();
  1191. if (FAILED(hRes))
  1192. {
  1193. ERRORTRACE((LOG_WBEMCORE, "Creation of system instances failed during repository creation <0x%X>!\n", hRes));
  1194. }
  1195. }
  1196. }
  1197. Objects[i]->Release();
  1198. }
  1199. }
  1200. if (SUCCEEDED(hRes))
  1201. {
  1202. hRes = SetSecurityForNS(pSession, pNs, pParentSession, pParentNs);
  1203. if (FAILED(hRes))
  1204. {
  1205. ERRORTRACE((LOG_WBEMCORE, "Setting of security on namespace failed during repository creation <0x%X>!\n", hRes));
  1206. }
  1207. }
  1208. pSvc->Release();
  1209. return hRes;
  1210. }
  1211. //***************************************************************************
  1212. //
  1213. //***************************************************************************
  1214. //
  1215. HRESULT CRepository::EnsureNsSystemRootObjects(
  1216. IN IWmiDbSession *pSession,
  1217. IN IWmiDbHandle *pNs,
  1218. IN IWmiDbSession *pParentSession,
  1219. IN IWmiDbHandle *pParentNs
  1220. )
  1221. {
  1222. HRESULT hRes;
  1223. // Do a get and see if __EventSinkCacheControl=@ is there.
  1224. // ========================================================
  1225. IWbemClassObject *pTestObj = 0;
  1226. hRes = GetObject(pSession, pNs, L"__EventSinkCacheControl=@", 0, &pTestObj);
  1227. if (SUCCEEDED(hRes))
  1228. {
  1229. pTestObj->Release();
  1230. return WBEM_S_NO_ERROR;
  1231. }
  1232. // If here, it's a new namespace that has to be populated with system classes.
  1233. // ===========================================================================
  1234. CCoreServices *pSvc = CCoreServices::CreateInstance();
  1235. if (pSvc == NULL)
  1236. return WBEM_E_OUT_OF_MEMORY;
  1237. CReleaseMe _rm(pSvc);
  1238. _IWmiObject *Objects[256];
  1239. ULONG uSize = 256;
  1240. hRes = pSvc->GetSystemObjects(GET_SYSTEM_ROOT_OBJECTS, &uSize, Objects);
  1241. if (SUCCEEDED(hRes))
  1242. {
  1243. for (int i = 0; i < uSize; i++)
  1244. {
  1245. IWbemClassObject *pObj;
  1246. if (SUCCEEDED(hRes))
  1247. {
  1248. hRes = Objects[i]->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pObj);
  1249. if (SUCCEEDED(hRes))
  1250. {
  1251. hRes = PutObject(pSession, pNs, IID_IWbemClassObject, pObj, WMIDB_DISABLE_EVENTS);
  1252. pObj->Release();
  1253. if (FAILED(hRes))
  1254. {
  1255. ERRORTRACE((LOG_WBEMCORE, "Creation of system root objects failed during repository creation <0x%X>!\n", hRes));
  1256. }
  1257. }
  1258. }
  1259. Objects[i]->Release();
  1260. }
  1261. }
  1262. return hRes;
  1263. }
  1264. //***************************************************************************
  1265. //
  1266. //***************************************************************************
  1267. //
  1268. HRESULT CRepository::EnsureNsSystemSecurityObjects(
  1269. IN IWmiDbSession *pSession,
  1270. IN IWmiDbHandle *pNs,
  1271. IN IWmiDbSession *pParentSession,
  1272. IN IWmiDbHandle *pParentNs
  1273. )
  1274. {
  1275. HRESULT hRes;
  1276. // Do a get and see if __User is there.
  1277. // ========================================================
  1278. IWbemClassObject *pTestObj = 0;
  1279. hRes = GetObject(pSession, pNs, L"__User", 0, &pTestObj);
  1280. if (SUCCEEDED(hRes))
  1281. {
  1282. pTestObj->Release();
  1283. return WBEM_S_NO_ERROR;
  1284. }
  1285. // If here, it's a new namespace that has to be populated with system classes.
  1286. // ===========================================================================
  1287. CCoreServices *pSvc = CCoreServices::CreateInstance();
  1288. if (pSvc == NULL)
  1289. return WBEM_E_OUT_OF_MEMORY;
  1290. _IWmiObject *Objects[256];
  1291. ULONG uSize = 256;
  1292. hRes = pSvc->GetSystemObjects(GET_SYSTEM_SECURITY_OBJECTS, &uSize, Objects);
  1293. if (SUCCEEDED(hRes))
  1294. {
  1295. for (int i = 0; i < uSize; i++)
  1296. {
  1297. IWbemClassObject *pObj;
  1298. if (SUCCEEDED(hRes))
  1299. {
  1300. hRes = Objects[i]->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pObj);
  1301. if (SUCCEEDED(hRes))
  1302. {
  1303. hRes = PutObject(pSession, pNs, IID_IWbemClassObject, pObj, WMIDB_DISABLE_EVENTS);
  1304. pObj->Release();
  1305. if (FAILED(hRes))
  1306. {
  1307. ERRORTRACE((LOG_WBEMCORE, "Creation of system security objects failed during repository creation <0x%X>!\n", hRes));
  1308. }
  1309. }
  1310. }
  1311. Objects[i]->Release();
  1312. }
  1313. }
  1314. pSvc->Release();
  1315. return hRes;
  1316. }
  1317. //***************************************************************************
  1318. //
  1319. // Adjusted for all repository drivers. Works for scopes or namespaces.
  1320. // If a scope is being opened, <pScope> will be set on return and
  1321. // <pbIsNamespace> will point to FALSE. Otherwise, <pScope> is set to
  1322. // point to NULL and <pbIsNamespace> points to TRUE.
  1323. //
  1324. // If <pszScope> is NULL, a pointer to the virtual ROOT in ESE
  1325. // is returned.
  1326. //
  1327. //***************************************************************************
  1328. //
  1329. HRESULT CRepository::OpenScope(
  1330. IN IWmiDbSession *pParentSession, //Parent session to use to
  1331. IN LPWSTR pszTargetScope, // NS or scope
  1332. IN GUID *pTransGuid, // Transaction GUID for connection
  1333. OUT IWmiDbController **pDriver, // Driver
  1334. OUT IWmiDbSession **pSession, // Session
  1335. OUT IWmiDbHandle **pScope, // Scope
  1336. OUT IWmiDbHandle **pNs // Nearest NS
  1337. )
  1338. {
  1339. HRESULT hRes;
  1340. ULONG uNsCount = 0;
  1341. // uScopeCount = 0;
  1342. if (pNs == 0 || pSession == 0)
  1343. return WBEM_E_INVALID_PARAMETER;
  1344. // Default settings.
  1345. // =================
  1346. if (pScope)
  1347. *pScope = 0;
  1348. *pNs = 0;
  1349. *pSession = 0;
  1350. if (pDriver)
  1351. *pDriver = 0;
  1352. // Check for virtual root ns (the parent to ROOT).
  1353. // ===============================================
  1354. if (pszTargetScope == 0)
  1355. {
  1356. if (m_pEseRoot == 0)
  1357. return WBEM_E_CRITICAL_ERROR;
  1358. if (pDriver)
  1359. {
  1360. m_pEseController->AddRef();
  1361. *pDriver = m_pEseController;
  1362. }
  1363. m_pEseSession->AddRef();
  1364. *pSession = m_pEseSession;
  1365. m_pEseRoot->AddRef();
  1366. *pNs = m_pEseRoot;
  1367. return WBEM_S_NO_ERROR;
  1368. }
  1369. // Parse the path.
  1370. // ===============
  1371. IWbemPath *pPath = ConfigMgr::GetNewPath();
  1372. if (pPath == 0)
  1373. return WBEM_E_OUT_OF_MEMORY;
  1374. CReleaseMe _1(pPath);
  1375. hRes = pPath->SetText(WBEMPATH_TREAT_SINGLE_IDENT_AS_NS | WBEMPATH_CREATE_ACCEPT_ALL , pszTargetScope);
  1376. if (FAILED(hRes))
  1377. return WBEM_E_INVALID_NAMESPACE;
  1378. // Analyze it. Is it just a namespace?
  1379. // Build the namespace string and normalize it.
  1380. // ============================================
  1381. hRes = pPath->GetNamespaceCount(&uNsCount);
  1382. //hRes = pPath->GetScopeCount(&uScopeCount);
  1383. // Starting handles at ROOT.
  1384. // =========================
  1385. IWmiDbHandle *pTempNs = 0;
  1386. IWmiDbHandle *pMostRecent = 0;
  1387. IWmiDbHandle *pMostRecentScope = 0;
  1388. IWmiDbSession *pTempSession = m_pEseSession; // Default virtual root
  1389. IWmiDbController *pTempDriver = m_pEseController; // Default driver
  1390. //Use the override if available
  1391. if (pParentSession)
  1392. pTempSession = pParentSession;
  1393. pTempSession->AddRef(); // For later release
  1394. pTempDriver->AddRef(); // For later release
  1395. hRes = OpenEseNs(pTempSession, L"ROOT", &pMostRecent);
  1396. if (FAILED(hRes))
  1397. {
  1398. pTempSession->Release();
  1399. pTempDriver->Release();
  1400. return WBEM_E_CRITICAL_ERROR;
  1401. }
  1402. // Starting driver.
  1403. // ================
  1404. WString sNsDecoration = "ROOT";
  1405. // open up each namespace successively, mapping it.
  1406. // ===============================================
  1407. for (ULONG u = 0; u < uNsCount; u++)
  1408. {
  1409. IWbemClassObject *pNsRep = 0;
  1410. ULONG uLen = 0;
  1411. // Get next namespace token name.
  1412. // ==============================
  1413. hRes = pPath->GetNamespaceAt(u, &uLen, NULL);
  1414. if(FAILED(hRes))
  1415. goto Error;
  1416. WCHAR* Buf = new WCHAR[uLen+1];
  1417. if (Buf == NULL)
  1418. {
  1419. hRes = WBEM_E_OUT_OF_MEMORY;
  1420. goto Error;
  1421. }
  1422. CVectorDeleteMe<WCHAR> vdm(Buf);
  1423. hRes = pPath->GetNamespaceAt(u, &uLen, Buf);
  1424. if (FAILED(hRes) || *Buf == 0)
  1425. goto Error;
  1426. if ((u == 0) && (wbem_wcsicmp(L"root", Buf) != 0))
  1427. {
  1428. hRes = WBEM_E_INVALID_NAMESPACE;
  1429. goto Error;
  1430. }
  1431. else if (u == 0)
  1432. continue;
  1433. // Build a relative scope path.
  1434. // ============================
  1435. WString sPath = "__namespace='";
  1436. sPath += Buf;
  1437. sPath += "'";
  1438. sNsDecoration += "\\";
  1439. sNsDecoration += Buf;
  1440. IWbemPath *pNewPath = ConfigMgr::GetNewPath();
  1441. if (pNewPath == 0)
  1442. {
  1443. hRes = WBEM_E_OUT_OF_MEMORY;
  1444. goto Error;
  1445. }
  1446. CReleaseMe rm1(pNewPath);
  1447. hRes = pNewPath->SetText(WBEMPATH_TREAT_SINGLE_IDENT_AS_NS | WBEMPATH_CREATE_ACCEPT_ALL , sPath);
  1448. if (FAILED(hRes))
  1449. goto Error;
  1450. // Get the reprsentation object.
  1451. // =============================
  1452. hRes = pTempSession->GetObjectDirect(pMostRecent, pNewPath, 0, IID_IWbemClassObject, (void **) &pNsRep);
  1453. if (hRes == WBEM_E_NOT_FOUND)
  1454. {
  1455. //If a namespace does not exist it should return a different namespace...
  1456. hRes = WBEM_E_INVALID_NAMESPACE;
  1457. goto Error;
  1458. }
  1459. else if (FAILED(hRes))
  1460. goto Error;
  1461. CReleaseMe _(pNsRep);
  1462. // Now move down one namespace.
  1463. // =============================
  1464. hRes = pTempSession->GetObject(pMostRecent, pNewPath, 0, WMIDB_HANDLE_TYPE_COOKIE, &pTempNs);
  1465. ReleaseIfNotNULL(pMostRecent);
  1466. pMostRecent = pTempNs;
  1467. pTempNs = 0;
  1468. if (FAILED(hRes))
  1469. goto Error;
  1470. }
  1471. // Final.
  1472. // ======
  1473. ReleaseIfNotNULL(pTempNs);
  1474. if (pScope)
  1475. *pScope = pMostRecentScope;
  1476. *pNs = pMostRecent;
  1477. *pSession = pTempSession;
  1478. if (pDriver)
  1479. *pDriver = pTempDriver;
  1480. return WBEM_S_NO_ERROR;
  1481. Error:
  1482. ReleaseIfNotNULL(pMostRecent);
  1483. ReleaseIfNotNULL(pTempNs);
  1484. ReleaseIfNotNULL(pTempDriver);
  1485. ReleaseIfNotNULL(pTempSession);
  1486. return hRes;
  1487. }
  1488. HRESULT CRepository::GetNewSession(IWmiDbSession **ppSession)
  1489. {
  1490. HRESULT hRes;
  1491. IWmiDbController *pController = 0;
  1492. WMIDB_LOGON_TEMPLATE *pTemplate = 0;
  1493. IWmiDbSession *pSession= 0;
  1494. IWmiDbHandle *pRoot = 0;
  1495. // Retrieve the CLSID of the default driver.
  1496. // =========================================
  1497. CLSID clsid;
  1498. hRes = ConfigMgr::GetDefaultRepDriverClsId(clsid);
  1499. if (FAILED(hRes))
  1500. return hRes;
  1501. hRes = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
  1502. IID_IWmiDbController, (void **)&pController);
  1503. if (FAILED(hRes))
  1504. return hRes;
  1505. CReleaseMe _1(pController);
  1506. hRes = pController->GetLogonTemplate(0x409, 0, &pTemplate);
  1507. if (FAILED(hRes))
  1508. return hRes;
  1509. hRes = pController->Logon(pTemplate, 0, WMIDB_HANDLE_TYPE_VERSIONED, &pSession, &pRoot);
  1510. if (SUCCEEDED(hRes))
  1511. {
  1512. *ppSession = pSession;
  1513. pRoot->Release();
  1514. }
  1515. pController->FreeLogonTemplate(&pTemplate);
  1516. return hRes;
  1517. }
  1518. HRESULT CRepository::UpgradeSystemClasses()
  1519. {
  1520. DWORD dwOldVer = 0;
  1521. DWORD dwNewVer = 0;
  1522. HRESULT hRes;
  1523. hRes = m_pEseController->GetRepositoryVersions(&dwOldVer, &dwNewVer);
  1524. if (FAILED(hRes))
  1525. return hRes;
  1526. if (dwOldVer < 4)
  1527. {
  1528. //Lower versions stored system classes in every namespace! We
  1529. //should delete them!
  1530. CWStringArray aListRootSystemClasses;
  1531. //Retrieve the list...
  1532. hRes = GetListOfRootSystemClasses(aListRootSystemClasses); // SEC:REVIEWED 2002-03-22 : Needs EH, throws on low-mem
  1533. if (SUCCEEDED(hRes))
  1534. {
  1535. //Create a new session...
  1536. IWmiDbSession *pSession = NULL;
  1537. IWmiDbSessionEx *pSessionEx = NULL;
  1538. hRes = CRepository::GetNewSession(&pSession);
  1539. if (FAILED(hRes))
  1540. return hRes;
  1541. //Get an EX version that supports transactioning...
  1542. pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pSessionEx);
  1543. if (pSessionEx)
  1544. {
  1545. pSession->Release();
  1546. pSession = pSessionEx;
  1547. }
  1548. CReleaseMe relMe1(pSession);
  1549. //If we have transactionable session, use it!
  1550. if (pSessionEx)
  1551. {
  1552. hRes = pSessionEx->BeginWriteTransaction(0);
  1553. if (FAILED(hRes))
  1554. {
  1555. return hRes;
  1556. }
  1557. }
  1558. try
  1559. {
  1560. //Recursively do the deletion, starting at root, however don't delete
  1561. //the ones in root itself!
  1562. hRes = RecursiveDeleteClassesFromNamespace(pSession, L"root", aListRootSystemClasses, false);
  1563. }
  1564. catch (CX_Exception &) // Only WStringArray should throw
  1565. {
  1566. hRes = WBEM_E_CRITICAL_ERROR;
  1567. }
  1568. if (SUCCEEDED(hRes))
  1569. {
  1570. //Commit the transaction
  1571. if (pSessionEx)
  1572. {
  1573. hRes = pSessionEx->CommitTransaction(0);
  1574. }
  1575. }
  1576. else
  1577. {
  1578. ERRORTRACE((LOG_WBEMCORE, "Removal of ROOT ONLY system classes from non-ROOT namespace failed during repository upgrade <0x%X>!\n", hRes));
  1579. if (pSessionEx)
  1580. pSessionEx->AbortTransaction(0);
  1581. }
  1582. }
  1583. }
  1584. return hRes;
  1585. }
  1586. HRESULT CRepository::GetListOfRootSystemClasses(CWStringArray &aListRootSystemClasses)
  1587. {
  1588. CCoreServices *pSvc = CCoreServices::CreateInstance();
  1589. if (pSvc == NULL)
  1590. return WBEM_E_OUT_OF_MEMORY;
  1591. _IWmiObject *Objects[256];
  1592. ULONG uSize = 256;
  1593. HRESULT hRes;
  1594. hRes = pSvc->GetSystemObjects(GET_SYSTEM_ROOT_OBJECTS, &uSize, Objects);
  1595. if (SUCCEEDED(hRes))
  1596. {
  1597. for (int i = 0; i < uSize; i++)
  1598. {
  1599. _IWmiObject *pObj;
  1600. if (SUCCEEDED(hRes))
  1601. {
  1602. hRes = Objects[i]->QueryInterface(IID__IWmiObject, (LPVOID *) &pObj);
  1603. if (SUCCEEDED(hRes))
  1604. {
  1605. if (pObj->IsObjectInstance() != S_OK)
  1606. {
  1607. VARIANT var;
  1608. VariantInit(&var);
  1609. hRes = pObj->Get(L"__CLASS", 0, &var, 0, 0);
  1610. if (SUCCEEDED(hRes) && (V_VT(&var) == VT_BSTR))
  1611. {
  1612. if (aListRootSystemClasses.Add(V_BSTR(&var)) != CWStringArray::no_error)
  1613. hRes = WBEM_E_OUT_OF_MEMORY;
  1614. }
  1615. VariantClear(&var);
  1616. }
  1617. pObj->Release();
  1618. }
  1619. }
  1620. Objects[i]->Release();
  1621. }
  1622. }
  1623. pSvc->Release();
  1624. return hRes;
  1625. }
  1626. //
  1627. //
  1628. // throws because of the WStringArray
  1629. //
  1630. //
  1631. HRESULT CRepository::RecursiveDeleteClassesFromNamespace(IWmiDbSession *pSession,
  1632. const wchar_t *wszNamespace,
  1633. CWStringArray &aListRootSystemClasses,
  1634. bool bDeleteInThisNamespace)
  1635. {
  1636. HRESULT hRes = WBEM_S_NO_ERROR;
  1637. IWmiDbHandle *pNs = NULL;
  1638. //Open Namespace
  1639. hRes = OpenEseNs(pSession, wszNamespace, &pNs);
  1640. CReleaseMe rmNS(pNs);
  1641. //Delete classes from this namespace if necessary
  1642. if (SUCCEEDED(hRes) && bDeleteInThisNamespace)
  1643. {
  1644. for (int i = 0; i != aListRootSystemClasses.Size(); i++)
  1645. {
  1646. hRes = DeleteByPath(pSession, pNs, aListRootSystemClasses[i], 0);
  1647. if (hRes == WBEM_E_NOT_FOUND)
  1648. hRes = WBEM_S_NO_ERROR;
  1649. else if (FAILED(hRes))
  1650. break;
  1651. }
  1652. }
  1653. if (FAILED(hRes)) return hRes;
  1654. //Special class that needs to be deleted is the __classes, and needs to go from all
  1655. //namespaces
  1656. hRes = DeleteByPath(pSession, pNs, L"__classes", 0);
  1657. if (hRes == WBEM_E_NOT_FOUND) hRes = WBEM_S_NO_ERROR;
  1658. if (FAILED(hRes)) return hRes;
  1659. //Enumerate child namespaces...
  1660. CWStringArray aListNamespaces;
  1661. CNamespaceListSink * pSink = new CNamespaceListSink(aListNamespaces); // SEC:REVIEWED 2002-03-22 : How does this object handle out-of-mem on the <aListNamespaces> ?
  1662. if (pSink == NULL) return WBEM_E_OUT_OF_MEMORY;
  1663. pSink->AddRef();
  1664. CReleaseMe rmSink(pSink);
  1665. hRes = ExecQuery(pSession, pNs, L"select * from __namespace", pSink, 0);
  1666. if (FAILED(hRes)) return hRes;
  1667. //Work through list and call ourselves with that namespace name...
  1668. for (int i = 0; i != aListNamespaces.Size(); i++)
  1669. {
  1670. //Build the full name of this namespace
  1671. size_t tmpLength = wcslen(wszNamespace) + wcslen(aListNamespaces[i]) + wcslen(L"\\") + 1;
  1672. wmilib::auto_buffer<WCHAR> wszChildNamespace( new WCHAR[tmpLength]);
  1673. if (wszChildNamespace.get() == NULL) return WBEM_E_OUT_OF_MEMORY;
  1674. StringCchCopyW(wszChildNamespace.get(), tmpLength, wszNamespace);
  1675. StringCchCatW(wszChildNamespace.get(), tmpLength, L"\\");
  1676. StringCchCatW(wszChildNamespace.get(), tmpLength, aListNamespaces[i]);
  1677. //Do the deletion...
  1678. hRes = RecursiveDeleteClassesFromNamespace(pSession, wszChildNamespace.get(), aListRootSystemClasses, true);
  1679. if (FAILED(hRes)) return hRes;
  1680. }
  1681. return hRes;
  1682. }