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.

6798 lines
229 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
  4. //
  5. // repdrvr.cpp
  6. //
  7. // cvadai 19-Mar-99 Created as prototype for Quasar.
  8. //
  9. //***************************************************************************
  10. #define _REPDRVR_CPP_
  11. #pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the
  12. #pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
  13. #define DBINITCONSTANTS // Initialize OLE constants...
  14. #define INITGUID // ...once in each app.
  15. #define _WIN32_DCOM
  16. #include "precomp.h"
  17. #include <std.h>
  18. #include <sqlexec.h>
  19. #include <sqlcache.h>
  20. #include <repdrvr.h>
  21. #include <wbemint.h>
  22. #include <math.h>
  23. #include <resource.h>
  24. #include <reputils.h>
  25. #include <crc64.h>
  26. #include <smrtptr.h>
  27. #include <wmiutils.h>
  28. #include <wbemtime.h>
  29. #include <reg.h>
  30. //#include <icecap.h>
  31. // Statics
  32. _WMILockit::_WMILockit(CRITICAL_SECTION *pCS)
  33. {
  34. EnterCriticalSection(pCS);
  35. m_cs = pCS;
  36. }
  37. _WMILockit::~_WMILockit()
  38. {
  39. LeaveCriticalSection(m_cs);
  40. }
  41. #define REPDRVR_FLAG_FLUSH_ALL 0x1
  42. extern long g_cObj;
  43. typedef std::map<SQL_ID, CacheInfo *> SchemaCache;
  44. typedef std::map<_bstr_t, SQL_ID, C_wchar_LessCase> PathIndex;
  45. typedef std::map <SQL_ID, LockData *> LockCache;
  46. typedef std::vector<LockItem *> LockList;
  47. typedef std::map <DWORD, DWORD> Properties;
  48. typedef std::vector <SessionLock *> SessionLocks;
  49. typedef std::map <DWORD, CESSHolder *> ESSObjs;
  50. typedef std::map<SQL_ID, bool> SQL_IDMap;
  51. typedef std::vector <SQL_ID> SQLIDs;
  52. typedef std::map <DWORD, SQLIDs> SessionDynasties;
  53. // Contrived method of generating proc names,
  54. // since we are limited to 30 characters.
  55. #define PROCTYPE_GET 1
  56. #define PROCTYPE_PUT 2
  57. #define PROCTYPE_DEL 3
  58. LPWSTR StripSlashes(LPWSTR lpText)
  59. {
  60. wchar_t *pszTemp = NULL;
  61. if (lpText)
  62. {
  63. pszTemp = new wchar_t [wcslen(lpText)+1];
  64. if (pszTemp)
  65. {
  66. int iPos = 0;
  67. int iLen = wcslen(lpText);
  68. if (iLen)
  69. {
  70. BOOL bOnSlash = FALSE;
  71. for (int i = 0; i < iLen; i++)
  72. {
  73. WCHAR t = lpText[i];
  74. if (t == '\\')
  75. {
  76. if (lpText[i+1] == '\\' && !bOnSlash)
  77. {
  78. bOnSlash = TRUE;
  79. continue;
  80. }
  81. }
  82. pszTemp[iPos] = t;
  83. bOnSlash = FALSE;
  84. iPos++;
  85. }
  86. }
  87. pszTemp[iPos] = '\0';
  88. }
  89. }
  90. return pszTemp;
  91. }
  92. int GetDiff(SYSTEMTIME tEnd, SYSTEMTIME tStart)
  93. {
  94. int iRet = 0;
  95. __int64 iTemp = (tEnd.wDay * 1000000000) +
  96. (tEnd.wHour * 10000000) +
  97. (tEnd.wMinute * 100000) +
  98. (tEnd.wSecond * 1000) +
  99. tEnd.wMilliseconds;
  100. iTemp -= ((tStart.wDay * 1000000000) +
  101. (tStart.wHour * 10000000) +
  102. (tStart.wMinute * 100000) +
  103. (tStart.wSecond * 1000) +
  104. tStart.wMilliseconds);
  105. iRet = (int) iTemp;
  106. return iRet;
  107. }
  108. CWbemClassObjectProps::CWbemClassObjectProps
  109. (CWmiDbSession *pSession, CSQLConnection *pConn, IWbemClassObject *pObj, CSchemaCache *pCache, SQL_ID dScopeID)
  110. {
  111. lpClassName = GetPropertyVal(L"__Class", pObj);
  112. lpNamespace = GetPropertyVal(L"__Namespace", pObj);
  113. lpSuperClass = GetPropertyVal(L"__SuperClass", pObj);
  114. lpDynasty = GetPropertyVal(L"__Dynasty", pObj);
  115. LPWSTR lpTemp = GetPropertyVal(L"__Genus", pObj);
  116. CDeleteMe <wchar_t> r(lpTemp);
  117. if (lpTemp)
  118. dwGenus = _wtoi(lpTemp);
  119. // If pConn is blank, this should already be loaded.
  120. if (pConn)
  121. {
  122. if (FAILED(pSession->LoadClassInfo(pConn, lpClassName, dScopeID, FALSE)))
  123. {
  124. if (lpSuperClass)
  125. pSession->LoadClassInfo(pConn, lpSuperClass, dScopeID, FALSE);
  126. }
  127. }
  128. if (dwGenus == 1)
  129. lpRelPath = GetPropertyVal(L"__Class", pObj);
  130. else
  131. {
  132. LPWSTR lpTemp = GetPropertyVal(L"__RelPath", pObj);
  133. CDeleteMe <wchar_t> d (lpTemp);
  134. lpRelPath = StripSlashes(lpTemp);
  135. if (lpRelPath)
  136. {
  137. LPWSTR lpNewClass = pCache->GetKeyRoot(lpClassName, dScopeID);
  138. if (lpNewClass)
  139. {
  140. LPWSTR lpPtr = lpRelPath + wcslen(lpClassName);
  141. LPWSTR lpTemp2 = new wchar_t [wcslen(lpNewClass) + wcslen(lpPtr) + 1];
  142. if (lpTemp2)
  143. {
  144. wcscpy(lpTemp2, lpNewClass);
  145. wcscat(lpTemp2, lpPtr);
  146. delete lpRelPath;
  147. lpRelPath = lpTemp2;
  148. }
  149. delete lpNewClass;
  150. }
  151. }
  152. }
  153. lpKeyString = NULL;
  154. }
  155. CWbemClassObjectProps::~CWbemClassObjectProps()
  156. {
  157. delete lpClassName;
  158. delete lpNamespace;
  159. delete lpRelPath;
  160. delete lpSuperClass;
  161. delete lpKeyString;
  162. delete lpDynasty;
  163. }
  164. //***************************************************************************
  165. //
  166. // ConvertBlobToObject
  167. //
  168. //***************************************************************************
  169. HRESULT ConvertBlobToObject (IWbemClassObject *pNewObj, BYTE *pBuffer, DWORD dwLen, _IWmiObject **ppNewObj)
  170. {
  171. HRESULT hr = WBEM_S_NO_ERROR;
  172. IWbemClassObject *pEmbed = NULL;
  173. _IWmiObject *pInt = NULL;
  174. if (pNewObj)
  175. hr = pNewObj->Clone(&pEmbed);
  176. else
  177. {
  178. _IWmiObject *pClass = NULL;
  179. // Handle blank Instance prototypes
  180. hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER,
  181. IID__IWmiObject, (void **)&pClass);
  182. CReleaseMe r (pClass);
  183. if (pClass)
  184. {
  185. hr = pClass->WriteProp(L"__Class", 0,
  186. 4, 4, CIM_STRING, L"X");
  187. if (SUCCEEDED(hr))
  188. {
  189. hr = pClass->SpawnInstance(0, &pEmbed);
  190. }
  191. }
  192. }
  193. if (SUCCEEDED(hr))
  194. {
  195. hr = pEmbed->QueryInterface(IID__IWmiObject, (void **)&pInt);
  196. CReleaseMe r (pInt);
  197. if (SUCCEEDED(hr))
  198. {
  199. LPVOID pTaskMem = NULL;
  200. if (SUCCEEDED(hr))
  201. {
  202. pTaskMem = CoTaskMemAlloc( dwLen );
  203. if ( NULL != pTaskMem )
  204. {
  205. // Copy the memory
  206. CopyMemory( pTaskMem, pBuffer, dwLen );
  207. hr = pInt->SetObjectMemory(pTaskMem, dwLen);
  208. if (SUCCEEDED(hr))
  209. {
  210. *ppNewObj = pInt;
  211. }
  212. else
  213. {
  214. _IWmiObject *pClass = NULL;
  215. hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER,
  216. IID__IWmiObject, (void **)&pClass);
  217. if (SUCCEEDED(hr))
  218. {
  219. hr = pClass->SetObjectMemory(pTaskMem, dwLen);
  220. if (SUCCEEDED(hr))
  221. {
  222. *ppNewObj = pClass;
  223. }
  224. }
  225. }
  226. }
  227. else
  228. {
  229. hr = WBEM_E_OUT_OF_MEMORY;
  230. }
  231. }
  232. }
  233. }
  234. return hr;
  235. }
  236. void ConvertDataToString(WCHAR * lpKey, BYTE* pData, DWORD dwType, BOOL bQuotes)
  237. {
  238. WCHAR *pFr;
  239. WCHAR *pTo, *pOrig;
  240. pFr = (LPWSTR)pData;
  241. switch(dwType)
  242. {
  243. case CIM_STRING:
  244. case CIM_REFERENCE:
  245. if (bQuotes)
  246. {
  247. pTo = lpKey;
  248. *pTo = L'\"';
  249. *pTo++;
  250. while (*pFr)
  251. {
  252. if (*pFr == L'\"')
  253. {
  254. *pTo = L'\\';
  255. *pTo++;
  256. *pTo = L'\"';
  257. }
  258. else
  259. *pTo = *pFr;
  260. pFr++;
  261. pTo++;
  262. }
  263. *pTo = L'\"';
  264. *pTo++;
  265. *pTo = L'\0';
  266. }
  267. else
  268. wcscpy(lpKey, (LPWSTR)pData);
  269. break;
  270. case CIM_SINT32:
  271. swprintf(lpKey, L"%d", *(int *)pData);
  272. break;
  273. case CIM_UINT32:
  274. swprintf(lpKey, L"%u", *(unsigned *)pData);
  275. break;
  276. case CIM_SINT16:
  277. swprintf(lpKey, L"%hd", *(signed short *)pData);
  278. break;
  279. case CIM_UINT16:
  280. swprintf(lpKey, L"%hu", *(unsigned short *)pData);
  281. break;
  282. case CIM_SINT8:
  283. swprintf(lpKey, L"%d", *(signed char *)pData);
  284. break;
  285. case CIM_UINT8:
  286. swprintf(lpKey, L"%u", *(unsigned char *)pData);
  287. break;
  288. case CIM_UINT64:
  289. swprintf(lpKey, L"%I64u", *(unsigned __int64 *)pData);
  290. break;
  291. case CIM_SINT64:
  292. swprintf(lpKey, L"%I64d", *(__int64 *)pData);
  293. break;
  294. case CIM_BOOLEAN:
  295. // String, either TRUE or FALSE
  296. if (*pFr)
  297. wcscpy(lpKey, L"TRUE");
  298. else
  299. wcscpy(lpKey, L"FALSE");
  300. break;
  301. default:
  302. break;
  303. }
  304. }
  305. HRESULT MakeKeyListString(SQL_ID dScopeId, CSchemaCache *pCache,
  306. LPWSTR lpClass, IWbemPathKeyList *pKeyList, LPWSTR lpKeyString)
  307. {
  308. HRESULT hr = 0;
  309. if (!pKeyList)
  310. return 0;
  311. if (!lpKeyString)
  312. return WBEM_E_INVALID_PARAMETER;
  313. ULONG uNumKeys = 0;
  314. hr = pKeyList->GetCount(&uNumKeys);
  315. if (SUCCEEDED(hr))
  316. {
  317. if (!uNumKeys)
  318. {
  319. ULONGLONG uIsSingleton = 0;
  320. hr = pKeyList->GetInfo(0, &uIsSingleton);
  321. if (SUCCEEDED(hr))
  322. {
  323. if (uIsSingleton)
  324. wcscat(lpKeyString, L"=@");
  325. else
  326. hr = WBEM_E_INVALID_PARAMETER;
  327. }
  328. }
  329. else
  330. {
  331. // Get the key list from the schema cache
  332. CWStringArray arrKeys;
  333. hr = pCache->GetKeys(dScopeId, lpClass, arrKeys);
  334. if (SUCCEEDED(hr))
  335. {
  336. if (arrKeys.Size() != uNumKeys)
  337. {
  338. hr = WBEM_E_INVALID_QUERY;
  339. }
  340. else
  341. {
  342. BOOL bFound = FALSE;
  343. for (int i = 0; i < arrKeys.Size(); i++)
  344. {
  345. bFound = FALSE;
  346. DWORD dwLen2 = 1024;
  347. BYTE bBuff[1024];
  348. wchar_t wName [1024];
  349. ULONG ct;
  350. for (ULONG j = 0; j < arrKeys.Size(); j++)
  351. {
  352. ULONG dwLen1 = 1024, dwLen2 = 1024;
  353. hr = pKeyList->GetKey(j, 0, &dwLen1, wName, &dwLen2, bBuff, &ct);
  354. if (SUCCEEDED(hr) && (!wcslen(wName) || !_wcsnicmp(wName, arrKeys.GetAt(i), 127)))
  355. {
  356. if (i > 0)
  357. wcscat(lpKeyString, L",");
  358. else
  359. wcscat(lpKeyString, L".");
  360. wcscat(lpKeyString, arrKeys.GetAt(i));
  361. wcscat(lpKeyString, L"=");
  362. wchar_t wValue[1024];
  363. ConvertDataToString(wValue, bBuff, ct, TRUE);
  364. if (FAILED(hr))
  365. break;
  366. wcscat(lpKeyString, wValue);
  367. bFound = TRUE;
  368. break;
  369. }
  370. }
  371. if (!bFound)
  372. hr = WBEM_E_INVALID_PARAMETER;
  373. if (FAILED(hr))
  374. break;
  375. }
  376. }
  377. }
  378. }
  379. }
  380. return hr;
  381. }
  382. BOOL IsDerivedFrom(IWbemClassObject *pObj, LPWSTR lpClassName, BOOL bDirectOnly)
  383. {
  384. BOOL bRet = FALSE;
  385. VARIANT vTemp;
  386. CClearMe c (&vTemp);
  387. LPWSTR lpClass = GetPropertyVal(L"__Class", pObj);
  388. CDeleteMe <wchar_t> d (lpClass);
  389. HRESULT hr = WBEM_S_NO_ERROR;
  390. if (!bDirectOnly)
  391. {
  392. if (!_wcsicmp(lpClassName, lpClass))
  393. bRet = TRUE;
  394. }
  395. if (!bRet)
  396. {
  397. hr = pObj->Get(L"__Derivation", 0, &vTemp, NULL, NULL);
  398. if (SUCCEEDED(hr))
  399. {
  400. SAFEARRAY *psaArray = V_ARRAY(&vTemp);
  401. if (psaArray)
  402. {
  403. long lLBound, lUBound;
  404. SafeArrayGetLBound(psaArray, 1, &lLBound);
  405. SafeArrayGetUBound(psaArray, 1, &lUBound);
  406. lUBound -= lLBound;
  407. lUBound += 1;
  408. for (int i = 0; i < lUBound; i++)
  409. {
  410. VARIANT vT2;
  411. VariantInit(&vT2);
  412. LPWSTR lpValue = NULL;
  413. hr = GetVariantFromArray(psaArray, i, VT_BSTR, vT2);
  414. lpValue = GetStr(vT2);
  415. CDeleteMe <wchar_t> r (lpValue);
  416. VariantClear(&vT2);
  417. if (lpValue && !_wcsicmp(lpValue, lpClassName))
  418. {
  419. bRet = TRUE;
  420. break;
  421. }
  422. }
  423. }
  424. }
  425. }
  426. return bRet;
  427. }
  428. POLARITY BOOL SetObjectAccess(
  429. IN HANDLE hObj)
  430. {
  431. PSECURITY_DESCRIPTOR pSD;
  432. DWORD dwLastErr = 0;
  433. BOOL bRet = FALSE;
  434. // no point if we arnt on nt
  435. pSD = (PSECURITY_DESCRIPTOR)CWin32DefaultArena::WbemMemAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
  436. if(pSD == NULL)
  437. return FALSE;
  438. ZeroMemory(pSD, SECURITY_DESCRIPTOR_MIN_LENGTH);
  439. if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
  440. goto Cleanup;
  441. if(!SetSecurityDescriptorDacl(pSD, TRUE, NULL, FALSE))
  442. goto Cleanup;
  443. bRet = SetKernelObjectSecurity(hObj, DACL_SECURITY_INFORMATION, pSD);
  444. Cleanup:
  445. if(bRet == FALSE)
  446. dwLastErr = GetLastError();
  447. CWin32DefaultArena::WbemMemFree(pSD);
  448. return bRet;
  449. }
  450. HINSTANCE CWmiDbController::GetResourceDll (LCID lLocale)
  451. {
  452. HINSTANCE hRCDll = NULL;
  453. wchar_t wLibName[501];
  454. GetModuleFileName(NULL, wLibName, 500);
  455. wchar_t *pLibName = wcsrchr(wLibName, L'\\');
  456. wchar_t *pTop = (wchar_t *)wLibName;
  457. if (pLibName)
  458. {
  459. int iPos = pLibName - pTop + 1;
  460. wLibName[iPos] = '\0';
  461. }
  462. swprintf(wLibName, L"%s%08X\\reprc.dll", wLibName, lLocale);
  463. hRCDll = LoadLibrary(wLibName);
  464. return hRCDll;
  465. }
  466. LPWSTR GetKeyString (LPWSTR lpString)
  467. {
  468. if (!lpString)
  469. return NULL;
  470. else
  471. return StripQuotes(lpString);
  472. }
  473. //***************************************************************************
  474. //
  475. // CWmiDbHandle::CWmiDbHandle
  476. //
  477. //***************************************************************************
  478. CWmiDbHandle::CWmiDbHandle()
  479. {
  480. m_dwHandleType = WMIDB_HANDLE_TYPE_NO_CACHE | WMIDB_HANDLE_TYPE_COOKIE;
  481. m_uRefCount = 0;
  482. m_bDefault = TRUE;
  483. m_bSecDesc = FALSE;
  484. m_dObjectId = 0;
  485. m_dClassId = 0;
  486. m_dwVersion = 1;
  487. m_pSession = NULL;
  488. m_pData = NULL;
  489. }
  490. //***************************************************************************
  491. //
  492. // CWmiDbHandle::CWmiDbHandle
  493. //
  494. //***************************************************************************
  495. CWmiDbHandle::~CWmiDbHandle()
  496. {
  497. }
  498. //***************************************************************************
  499. //
  500. // CWmiDbHandle::QueryInterface
  501. //
  502. //***************************************************************************
  503. HRESULT STDMETHODCALLTYPE CWmiDbHandle::QueryInterface(
  504. /* [in] */ REFIID riid,
  505. /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
  506. {
  507. *ppvObject = 0;
  508. if (IID_IUnknown==riid || IID_IWmiDbHandle==riid )
  509. {
  510. *ppvObject = (IWmiDbHandle*)this;
  511. AddRef();
  512. return S_OK;
  513. }
  514. else if (IID_IWbemClassObject == riid ||
  515. IID__IWmiObject == riid)
  516. {
  517. if (!m_pData && m_pSession && m_dwHandleType != WMIDB_HANDLE_TYPE_INVALID)
  518. {
  519. if (m_dObjectId)
  520. {
  521. HRESULT hr = QueryInterface_Internal(NULL, ppvObject);
  522. return hr;
  523. }
  524. }
  525. else if (m_pData)
  526. {
  527. *ppvObject = m_pData;
  528. m_pData->AddRef();
  529. return S_OK;
  530. }
  531. else
  532. return E_HANDLE;
  533. }
  534. return E_NOINTERFACE;
  535. }
  536. //***************************************************************************
  537. //
  538. // CWmiDbHandle::QueryInterface_Internal
  539. //
  540. //***************************************************************************
  541. HRESULT CWmiDbHandle::QueryInterface_Internal(CSQLConnection *pConn, void __RPC_FAR *__RPC_FAR *ppvObject,
  542. LPWSTR lpKey)
  543. {
  544. IWbemClassObject *pNew = NULL;
  545. HRESULT hr = WBEM_S_NO_ERROR;
  546. try
  547. {
  548. if (m_pData)
  549. {
  550. *ppvObject = m_pData;
  551. m_pData->AddRef();
  552. return S_OK;
  553. }
  554. else
  555. {
  556. hr = ((CWmiDbSession *)m_pSession)->GetObjectData(pConn, m_dObjectId, m_dClassId, m_dScopeId,
  557. m_dwHandleType, m_dwVersion, &pNew, FALSE, lpKey, m_bSecDesc);
  558. if (SUCCEEDED(hr) && pNew)
  559. {
  560. *ppvObject = (IWbemClassObject *)pNew;
  561. // Cookie handles must be reread each time.
  562. if ((m_dwHandleType & 0xF) != WMIDB_HANDLE_TYPE_COOKIE)
  563. {
  564. _WMILockit lkt(((CWmiDbSession *)m_pSession)->GetCS());
  565. m_pData = pNew;
  566. pNew->AddRef(); // For ourselves.
  567. }
  568. return S_OK;
  569. }
  570. else if (SUCCEEDED(hr))
  571. hr = WBEM_E_FAILED;
  572. else if (hr == WBEM_E_CRITICAL_ERROR &&
  573. (!m_pSession || !((CWmiDbSession *)m_pSession)->m_pController))
  574. hr = WBEM_E_SHUTTING_DOWN;
  575. }
  576. }
  577. catch (...)
  578. {
  579. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbHandle::QueryInterface_Internal (%I64d)\n", m_dObjectId));
  580. hr = WBEM_E_CRITICAL_ERROR;
  581. }
  582. return hr;
  583. }
  584. //***************************************************************************
  585. //
  586. // CWmiDbHandle::AddRef
  587. //
  588. //***************************************************************************
  589. ULONG STDMETHODCALLTYPE CWmiDbHandle::AddRef( )
  590. {
  591. if (m_pSession)
  592. m_pSession->AddRef();
  593. // We can't safely keep track of this
  594. // so we will only addref it once.
  595. // ==================================
  596. //if (m_pData)
  597. // m_pData->AddRef();
  598. InterlockedIncrement((LONG *) &m_uRefCount);
  599. return m_uRefCount;
  600. }
  601. //***************************************************************************
  602. //
  603. // CWmiDbHandle::Release
  604. //
  605. //***************************************************************************
  606. ULONG STDMETHODCALLTYPE CWmiDbHandle::Release( )
  607. {
  608. ULONG uNewCount = m_uRefCount;
  609. uNewCount = InterlockedDecrement((LONG *) &m_uRefCount);
  610. HRESULT hr = 0;
  611. try
  612. {
  613. // Only if we haven't shut down.
  614. if (m_pSession && (((CWmiDbSession *)m_pSession)->m_pController))
  615. {
  616. if (!uNewCount)
  617. {
  618. if ((m_dwHandleType & 0xF000) == WMIDB_HANDLE_TYPE_AUTODELETE)
  619. {
  620. hr = ((CWmiDbSession *)m_pSession)->Delete((IWmiDbHandle *)this);
  621. if (FAILED(hr))
  622. return uNewCount;
  623. }
  624. else if (m_dwHandleType != WMIDB_HANDLE_TYPE_INVALID)
  625. {
  626. ((CWmiDbSession *)m_pSession)->CleanCache(m_dObjectId, m_dwHandleType, this);
  627. }
  628. if (((CWmiDbSession *)m_pSession)->m_pController)
  629. ((CWmiDbController *)((CWmiDbSession *)m_pSession)->m_pController)->SubtractHandle();
  630. ((CWmiDbSession *)m_pSession)->UnlockDynasties();
  631. }
  632. m_pSession->Release();
  633. }
  634. }
  635. catch (...)
  636. {
  637. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbHandle::Release (%I64d)\n", m_dObjectId));
  638. hr = WBEM_E_CRITICAL_ERROR;
  639. }
  640. if (0 != uNewCount)
  641. return uNewCount;
  642. // To be safe, we will only add ref
  643. // this once, and release it once.
  644. // ================================
  645. if (m_pData)
  646. m_pData->Release();
  647. delete this;
  648. return uNewCount;
  649. }
  650. //***************************************************************************
  651. //
  652. // CWmiDbHandle::GetHandleType
  653. //
  654. //***************************************************************************
  655. HRESULT STDMETHODCALLTYPE CWmiDbHandle::GetHandleType(
  656. /* [out] */ DWORD __RPC_FAR *pdwType)
  657. {
  658. HRESULT hr = WBEM_S_NO_ERROR;
  659. if (pdwType)
  660. *pdwType = m_dwHandleType;
  661. else
  662. hr = WBEM_E_INVALID_PARAMETER;
  663. return hr;
  664. }
  665. //***************************************************************************
  666. //
  667. // CESSManager::CESSManager
  668. //
  669. //***************************************************************************
  670. CESSManager::CESSManager()
  671. {
  672. m_EventSubSys = NULL;
  673. }
  674. //***************************************************************************
  675. //
  676. // CESSManager::~CESSManager
  677. //
  678. //***************************************************************************
  679. CESSManager::~CESSManager()
  680. {
  681. // Release our ESS pointer.
  682. if (m_EventSubSys)
  683. m_EventSubSys->Release();
  684. }
  685. //***************************************************************************
  686. //
  687. // CESSManager::InitializeESS
  688. //
  689. //***************************************************************************
  690. void CESSManager::InitializeESS()
  691. {
  692. HRESULT hres = CoCreateInstance(CLSID_IWmiCoreServices, NULL,
  693. CLSCTX_INPROC_SERVER, IID__IWmiCoreServices,
  694. (void**)&m_EventSubSys);
  695. if(FAILED(hres))
  696. {
  697. ERRORTRACE((LOG_WBEMCORE,"CRITICAL: Event system not available!!!!\n"));
  698. }
  699. }
  700. //***************************************************************************
  701. //
  702. // CESSManager::AddInsertRecord
  703. //
  704. //***************************************************************************
  705. HRESULT CESSManager::AddInsertRecord(CSQLConnection *pConn, LPWSTR lpGUID, LPWSTR lpNamespace, LPWSTR lpClass, DWORD dwGenus,
  706. IWbemClassObject *pOldObj, IWbemClassObject *pNewObj)
  707. {
  708. HRESULT hr = WBEM_S_NO_ERROR;
  709. if (m_EventSubSys)
  710. {
  711. if (lpGUID && wcslen(lpGUID))
  712. {
  713. // Write record to the database.
  714. hr = CSQLExecProcedure::InsertUncommittedEvent(pConn, lpGUID, lpNamespace, lpClass,
  715. pOldObj, pNewObj, m_Schema);
  716. }
  717. else
  718. {
  719. long lType = 0;
  720. if (!pOldObj && pNewObj)
  721. {
  722. if (dwGenus == 1)
  723. lType = WBEM_EVENTTYPE_ClassCreation;
  724. else
  725. {
  726. if (IsDerivedFrom(pNewObj, L"__Namespace"))
  727. lType = WBEM_EVENTTYPE_NamespaceCreation;
  728. else
  729. lType = WBEM_EVENTTYPE_InstanceCreation;
  730. }
  731. }
  732. else
  733. {
  734. if (dwGenus == 1)
  735. lType = WBEM_EVENTTYPE_ClassModification;
  736. else
  737. {
  738. if (IsDerivedFrom(pOldObj, L"__Namespace"))
  739. lType = WBEM_EVENTTYPE_NamespaceModification;
  740. else
  741. lType = WBEM_EVENTTYPE_InstanceModification;
  742. }
  743. }
  744. CESSHolder *pHolder = new CESSHolder (lType, lpNamespace, lpClass,
  745. (_IWmiObject *)pOldObj, (_IWmiObject *)pNewObj);
  746. if (!pHolder)
  747. hr = WBEM_E_OUT_OF_MEMORY;
  748. m_ESSObjs[GetCurrentThreadId()] = pHolder;
  749. }
  750. }
  751. return hr;
  752. }
  753. //***************************************************************************
  754. //
  755. // CESSManager::AddDeleteRecord
  756. //
  757. //***************************************************************************
  758. HRESULT CESSManager::AddDeleteRecord(CSQLConnection *pConn, LPWSTR lpGUID, LPWSTR lpNamespace, LPWSTR lpClass, DWORD dwGenus,
  759. IWbemClassObject *pObj)
  760. {
  761. HRESULT hr = WBEM_S_NO_ERROR;
  762. if (m_EventSubSys)
  763. {
  764. // Write record to the database
  765. if (lpGUID && wcslen(lpGUID))
  766. {
  767. // Write record to the database.
  768. hr = CSQLExecProcedure::InsertUncommittedEvent(pConn, lpGUID, lpNamespace, lpClass, NULL,
  769. pObj, m_Schema);
  770. }
  771. else
  772. {
  773. long lType = 0;
  774. if (dwGenus == 1)
  775. lType = WBEM_EVENTTYPE_ClassDeletion;
  776. else
  777. {
  778. if (IsDerivedFrom(pObj, L"__Namespace"))
  779. lType = WBEM_EVENTTYPE_NamespaceDeletion;
  780. else
  781. lType = WBEM_EVENTTYPE_InstanceDeletion;
  782. }
  783. CESSHolder *pHolder = new CESSHolder (lType, lpNamespace, lpClass, (_IWmiObject *)pObj, NULL);
  784. if (!pHolder)
  785. hr = WBEM_E_OUT_OF_MEMORY;
  786. m_ESSObjs[GetCurrentThreadId()] = pHolder;
  787. }
  788. }
  789. return hr;
  790. }
  791. //***************************************************************************
  792. //
  793. // CESSManager::CommitAll
  794. //
  795. //***************************************************************************
  796. HRESULT CESSManager::CommitAll(LPCWSTR lpGUID, LPCWSTR lpRootNs)
  797. {
  798. HRESULT hr = WBEM_S_NO_ERROR;
  799. if (m_EventSubSys)
  800. {
  801. if (lpGUID && wcslen(lpGUID))
  802. {
  803. CSQLConnection *pConn = NULL;
  804. hr = m_Conns->GetConnection(&pConn, FALSE, FALSE, 30);
  805. if (SUCCEEDED(hr))
  806. {
  807. hr = CSQLExecProcedure::CommitEvents(pConn, m_EventSubSys,
  808. lpRootNs, lpGUID, m_Schema, m_Objects);
  809. m_Conns->ReleaseConnection(pConn);
  810. }
  811. }
  812. else
  813. {
  814. DWORD dwThread = GetCurrentThreadId();
  815. CESSHolder *pH = m_ESSObjs[dwThread];
  816. if (pH)
  817. pH->Deliver(m_EventSubSys, lpRootNs);
  818. delete pH;
  819. m_ESSObjs[dwThread] = NULL;
  820. }
  821. }
  822. return hr;
  823. }
  824. //***************************************************************************
  825. //
  826. // CESSManager::DeleteAll
  827. //
  828. //***************************************************************************
  829. HRESULT CESSManager::DeleteAll(LPCWSTR lpGUID)
  830. {
  831. HRESULT hr = WBEM_S_NO_ERROR;
  832. // Delete from DB
  833. if (m_EventSubSys)
  834. {
  835. if (lpGUID && wcslen(lpGUID))
  836. {
  837. CSQLConnection *pConn = NULL;
  838. hr = m_Conns->GetConnection(&pConn, FALSE, FALSE, 30);
  839. if (SUCCEEDED(hr))
  840. {
  841. hr = CSQLExecProcedure::DeleteUncommittedEvents(pConn, lpGUID, m_Schema, m_Objects);
  842. m_Conns->ReleaseConnection(pConn);
  843. }
  844. }
  845. else
  846. {
  847. DWORD dwThread = GetCurrentThreadId();
  848. CESSHolder *pH = m_ESSObjs[dwThread];
  849. delete pH;
  850. m_ESSObjs[dwThread] = NULL;
  851. }
  852. }
  853. return hr;
  854. }
  855. //***************************************************************************
  856. //
  857. // CESSHolder::CESSHolder
  858. //
  859. //***************************************************************************
  860. CESSHolder::CESSHolder(long lType, LPWSTR lpNs, LPWSTR lpClass, _IWmiObject *pOld, _IWmiObject *pNew)
  861. {
  862. m_lType = lType;
  863. if (lpNs && wcslen(lpNs))
  864. m_sNamespace = lpNs;
  865. else
  866. m_sNamespace = L"";
  867. m_sClass = lpClass;
  868. if (pOld)
  869. pOld->AddRef();
  870. if (pNew)
  871. pNew->AddRef();
  872. pOldObject = pOld;
  873. pNewObject = pNew;
  874. }
  875. //***************************************************************************
  876. //
  877. // CESSHolder::Deliver
  878. //
  879. //***************************************************************************
  880. HRESULT CESSHolder::Deliver (_IWmiCoreServices *pCS, LPCWSTR lpRootNs)
  881. {
  882. HRESULT hr = WBEM_S_NO_ERROR;
  883. DWORD dwNumObjs = 0;
  884. if (pOldObject)
  885. dwNumObjs++;
  886. if (pNewObject)
  887. dwNumObjs++;
  888. _bstr_t sTemp = L"\\\\.\\";
  889. sTemp += lpRootNs;
  890. if (m_sNamespace.length() && _wcsnicmp(m_sNamespace, L"root", 4))
  891. {
  892. sTemp += L"\\";
  893. sTemp += m_sNamespace;
  894. }
  895. _IWmiObject **pObjs = new _IWmiObject * [dwNumObjs];
  896. if (pObjs)
  897. {
  898. if (pNewObject)
  899. pObjs[0] = pNewObject;
  900. else
  901. pObjs[0] = pOldObject;
  902. if (pOldObject && pNewObject)
  903. pObjs[1] = pOldObject;
  904. hr = pCS->DeliverIntrinsicEvent(sTemp, m_lType, NULL,
  905. m_sClass, NULL, dwNumObjs, pObjs);
  906. delete pObjs;
  907. if (pOldObject)
  908. pOldObject->Release();
  909. if (pNewObject)
  910. pNewObject->Release();
  911. }
  912. else
  913. hr = WBEM_E_OUT_OF_MEMORY;
  914. return hr;
  915. }
  916. //***************************************************************************
  917. //
  918. // CWmiDbController::CWmiDbController
  919. //
  920. //***************************************************************************
  921. CWmiDbController::CWmiDbController()
  922. {
  923. InitializeCriticalSection(&m_cs);
  924. m_dwTimeOut = 10*1000; // 30 seconds default
  925. m_dwCurrentStatus = 0; // No status
  926. m_uRefCount = 0;
  927. m_pIMalloc = NULL;
  928. m_InitProperties = NULL;
  929. m_rgInitPropSet = NULL;
  930. m_dwTotalHits = 0;
  931. m_dwCacheHits = 0;
  932. m_dwTotalHandles = 0;
  933. m_bCacheInit = 0;
  934. m_bIsAdmin = 0;
  935. m_bESSEnabled = 0;
  936. CoInitialize(NULL);
  937. ESSMgr.SetConnCache(&ConnCache);
  938. ESSMgr.SetObjectCache(&ObjectCache);
  939. ESSMgr.SetSchemaCache(&SchemaCache);
  940. }
  941. //***************************************************************************
  942. //
  943. // CWmiDbController::CWmiDbController
  944. //
  945. //***************************************************************************
  946. CWmiDbController::~CWmiDbController()
  947. {
  948. Shutdown(0);
  949. if (m_pIMalloc)
  950. m_pIMalloc->Release();
  951. delete m_InitProperties;
  952. delete m_rgInitPropSet;
  953. g_cObj--;
  954. DeleteCriticalSection(&m_cs);
  955. }
  956. //***************************************************************************
  957. //
  958. // CWmiDbController::QueryInterface
  959. //
  960. //***************************************************************************
  961. HRESULT STDMETHODCALLTYPE CWmiDbController::QueryInterface(
  962. /* [in] */ REFIID riid,
  963. /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
  964. {
  965. *ppvObject = 0;
  966. if (IID_IUnknown==riid || IID_IWmiDbController==riid )
  967. {
  968. *ppvObject = (IWmiDbController*)this;
  969. AddRef();
  970. return S_OK;
  971. }
  972. return E_NOINTERFACE;
  973. }
  974. //***************************************************************************
  975. //
  976. // CWmiDbController::AddRef
  977. //
  978. //***************************************************************************
  979. ULONG STDMETHODCALLTYPE CWmiDbController::AddRef( )
  980. {
  981. InterlockedIncrement((LONG *) &m_uRefCount);
  982. return m_uRefCount;
  983. }
  984. //***************************************************************************
  985. //
  986. // CWmiDbController::Release
  987. //
  988. //***************************************************************************
  989. ULONG STDMETHODCALLTYPE CWmiDbController::Release( )
  990. {
  991. ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount);
  992. if (0 != uNewCount)
  993. return uNewCount;
  994. delete this;
  995. return WBEM_S_NO_ERROR;
  996. }
  997. //***************************************************************************
  998. //
  999. // CWmiDbController::FreeLogonTemplate
  1000. //
  1001. //***************************************************************************
  1002. HRESULT STDMETHODCALLTYPE CWmiDbController::FreeLogonTemplate(
  1003. /* [out][in] */ WMIDB_LOGON_TEMPLATE __RPC_FAR *__RPC_FAR *pTemplate)
  1004. {
  1005. HRESULT hr = WBEM_S_NO_ERROR;
  1006. try
  1007. {
  1008. if (!pTemplate || !*pTemplate)
  1009. hr = WBEM_E_INVALID_PARAMETER;
  1010. else
  1011. {
  1012. WMIDB_LOGON_TEMPLATE *pTemp = *pTemplate;
  1013. for (int i = 0; i < (int)pTemp->dwArraySize; i++)
  1014. {
  1015. VariantClear(&(pTemp->pParm[i].Value));
  1016. SysFreeString(pTemp->pParm[i].strParmDisplayName);
  1017. }
  1018. delete []pTemp->pParm;
  1019. delete *pTemplate;
  1020. *pTemplate = NULL;
  1021. }
  1022. }
  1023. catch (...)
  1024. {
  1025. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::FreeLogonTemplate\n"));
  1026. hr = WBEM_E_CRITICAL_ERROR;
  1027. }
  1028. return hr;
  1029. }
  1030. //***************************************************************************
  1031. //
  1032. // CWmiDbController::Logon
  1033. //
  1034. //***************************************************************************
  1035. HRESULT STDMETHODCALLTYPE CWmiDbController::Logon(
  1036. /* [in] */ WMIDB_LOGON_TEMPLATE __RPC_FAR *pLogonParms,
  1037. /* [in] */ DWORD dwFlags,
  1038. /* [in] */ DWORD dwRequestedHandleType,
  1039. /* [out] */ IWmiDbSession __RPC_FAR *__RPC_FAR *ppSession,
  1040. /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppRootNamespace)
  1041. {
  1042. HRESULT hr = WBEM_S_NO_ERROR;
  1043. if (!pLogonParms)
  1044. return WBEM_E_INVALID_PARAMETER;
  1045. if (dwFlags &~ WMIDB_FLAG_NO_INIT &~ WMIDB_FLAG_ADMIN_VERIFIED)
  1046. return WBEM_E_INVALID_PARAMETER;
  1047. // Not yet clear what we need to do.
  1048. // Best guess is: we get a SQL connection, shove it into an IWmiDbSession,
  1049. // and give it back to the user.
  1050. try
  1051. {
  1052. if (m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  1053. hr = WBEM_E_SHUTTING_DOWN;
  1054. else
  1055. {
  1056. if (!ppSession)
  1057. hr = WBEM_E_INVALID_PARAMETER;
  1058. else
  1059. {
  1060. _WMILockit lkt(&m_cs);
  1061. IWmiDbSession *pSession = NULL;
  1062. hr = GetUnusedSession(pLogonParms, dwFlags, dwRequestedHandleType, &pSession);
  1063. if (SUCCEEDED(hr))
  1064. {
  1065. *ppSession = pSession; // hopefully this interface will be corrected...
  1066. if (!(dwFlags & WMIDB_FLAG_NO_INIT))
  1067. {
  1068. if (!m_bCacheInit)
  1069. {
  1070. hr = ((CWmiDbSession *)pSession)->LoadSchemaCache();
  1071. // We don't want to return a handle if we couldn't load the schema cache.
  1072. if (SUCCEEDED(hr))
  1073. m_bCacheInit = TRUE;
  1074. }
  1075. if (dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)
  1076. m_bIsAdmin = TRUE;
  1077. // Now see if we can get a handle to the root namespace...
  1078. hr = ((CWmiDbSession *)pSession)->GetObject_Internal(L"root", dwFlags, dwRequestedHandleType, NULL, ppRootNamespace);
  1079. ((CWmiDbSession *)pSession)->m_sNamespacePath = L"root"; // Temporary default
  1080. wchar_t wMachineName[1024];
  1081. DWORD dwLen=1024;
  1082. if (!GetComputerName(wMachineName, &dwLen)) {
  1083. hr = GetLastError();
  1084. return WBEM_E_FAILED;
  1085. }
  1086. ((CWmiDbSession *)pSession)->m_sMachineName = wMachineName;
  1087. if (!m_bESSEnabled)
  1088. {
  1089. ESSMgr.InitializeESS();
  1090. if (ESSMgr.m_EventSubSys)
  1091. m_bESSEnabled = TRUE;
  1092. }
  1093. }
  1094. else if (ppRootNamespace)
  1095. *ppRootNamespace = NULL;
  1096. }
  1097. }
  1098. }
  1099. }
  1100. catch (...)
  1101. {
  1102. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::Logon\n"));
  1103. hr = WBEM_E_CRITICAL_ERROR;
  1104. }
  1105. return hr;
  1106. }
  1107. //***************************************************************************
  1108. //
  1109. // CWmiDbController::Shutdown
  1110. //
  1111. //***************************************************************************
  1112. HRESULT STDMETHODCALLTYPE CWmiDbController::Shutdown(
  1113. /* [in] */ DWORD dwFlags)
  1114. {
  1115. HRESULT hr = WBEM_S_NO_ERROR;
  1116. if (dwFlags != 0)
  1117. return WBEM_E_INVALID_PARAMETER;
  1118. if (m_dwCurrentStatus)
  1119. hr = m_dwCurrentStatus;
  1120. else
  1121. m_dwCurrentStatus = WBEM_E_SHUTTING_DOWN;
  1122. try
  1123. {
  1124. FlushCache(REPDRVR_FLAG_FLUSH_ALL);
  1125. hr = ConnCache.ClearConnections();
  1126. for (int i = 0; i < m_Sessions.size(); i++)
  1127. {
  1128. IWmiDbSession *pSession = m_Sessions[i];
  1129. if (pSession)
  1130. {
  1131. ((CWmiDbSession *)pSession)->ShutDown();
  1132. pSession->Release();
  1133. }
  1134. }
  1135. m_Sessions.clear();
  1136. }
  1137. catch (...)
  1138. {
  1139. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::Shutdown\n"));
  1140. hr = WBEM_E_CRITICAL_ERROR;
  1141. }
  1142. return hr;
  1143. }
  1144. //***************************************************************************
  1145. //
  1146. // CWmiDbController::SetCallTimeout
  1147. //
  1148. //***************************************************************************
  1149. HRESULT STDMETHODCALLTYPE CWmiDbController::SetCallTimeout(
  1150. /* [in] */ DWORD dwMaxTimeout)
  1151. {
  1152. HRESULT hr = WBEM_S_NO_ERROR;
  1153. if (dwMaxTimeout < 1000)
  1154. return WBEM_E_INVALID_PARAMETER;
  1155. if (m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  1156. hr = WBEM_E_SHUTTING_DOWN;
  1157. else
  1158. m_dwTimeOut = dwMaxTimeout;
  1159. return hr;
  1160. }
  1161. //***************************************************************************
  1162. //
  1163. // CWmiDbController::SetCacheValue
  1164. //
  1165. //***************************************************************************
  1166. HRESULT STDMETHODCALLTYPE CWmiDbController::SetCacheValue(
  1167. /* [in] */ DWORD dwMaxBytes)
  1168. {
  1169. HRESULT hr = WBEM_S_NO_ERROR;
  1170. try
  1171. {
  1172. if (m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  1173. hr = WBEM_E_SHUTTING_DOWN;
  1174. else
  1175. {
  1176. ObjectCache.SetCacheSize(dwMaxBytes);
  1177. SchemaCache.SetMaxSize(dwMaxBytes);
  1178. }
  1179. }
  1180. catch (...)
  1181. {
  1182. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::SetCacheValue\n"));
  1183. hr = WBEM_E_CRITICAL_ERROR;
  1184. }
  1185. return hr;
  1186. }
  1187. //***************************************************************************
  1188. //
  1189. // CWmiDbController::FlushCache
  1190. //
  1191. //***************************************************************************
  1192. HRESULT STDMETHODCALLTYPE CWmiDbController::FlushCache(
  1193. DWORD dwFlags)
  1194. {
  1195. HRESULT hr = WBEM_S_NO_ERROR;
  1196. try
  1197. {
  1198. // Remove all data from the cache.
  1199. {
  1200. _WMILockit lkt(&m_cs);
  1201. ObjectCache.EmptyCache();
  1202. }
  1203. if (dwFlags == REPDRVR_FLAG_FLUSH_ALL)
  1204. {
  1205. // Remove all SQL connections. We will reconnect later.
  1206. hr = ConnCache.ClearConnections();
  1207. // Clear all internal caches. These will be restored on the next connection.
  1208. {
  1209. _WMILockit lkt(&m_cs);
  1210. SchemaCache.EmptyCache();
  1211. }
  1212. m_bCacheInit = FALSE;
  1213. }
  1214. }
  1215. catch (...)
  1216. {
  1217. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::FlushCache\n"));
  1218. hr = WBEM_E_CRITICAL_ERROR;
  1219. }
  1220. return hr;
  1221. }
  1222. //***************************************************************************
  1223. //
  1224. // CWmiDbController::GetStatistics
  1225. //
  1226. //***************************************************************************
  1227. HRESULT STDMETHODCALLTYPE CWmiDbController::GetStatistics(
  1228. /* [in] */ DWORD dwParameter,
  1229. /* [out] */ DWORD __RPC_FAR *pdwValue)
  1230. {
  1231. HRESULT hr = WBEM_S_NO_ERROR;
  1232. DWORD dwTemp1 = 0;
  1233. DWORD dwTemp2 = 0;
  1234. _WMILockit _lk(&m_cs);
  1235. try
  1236. {
  1237. if (!pdwValue)
  1238. hr = WBEM_E_INVALID_PARAMETER;
  1239. else
  1240. {
  1241. switch (dwParameter)
  1242. {
  1243. case WMIDB_FLAG_TOTAL_HANDLES:
  1244. *pdwValue = m_dwTotalHandles;
  1245. break;
  1246. case WMIDB_FLAG_CACHE_SATURATION:
  1247. ObjectCache.GetCurrentUsage(dwTemp1);
  1248. ObjectCache.GetCacheSize(dwTemp2);
  1249. if (dwTemp2 > 0)
  1250. *pdwValue = 100*(((double)dwTemp1/(double)dwTemp2));
  1251. break;
  1252. case WMIDB_FLAG_CACHE_HIT_RATE:
  1253. if (m_dwTotalHits > 0)
  1254. *pdwValue = 100*((double)m_dwCacheHits / (double)m_dwTotalHits);
  1255. break;
  1256. default:
  1257. hr = WBEM_E_NOT_SUPPORTED;
  1258. break;
  1259. }
  1260. }
  1261. }
  1262. catch (...)
  1263. {
  1264. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::GetStatistics\n"));
  1265. hr = WBEM_E_CRITICAL_ERROR;
  1266. }
  1267. return hr;
  1268. }
  1269. //***************************************************************************
  1270. //
  1271. // CWmiDbController::GetUnusedSession
  1272. //
  1273. //***************************************************************************
  1274. HRESULT CWmiDbController::GetUnusedSession(WMIDB_LOGON_TEMPLATE *pLogon,
  1275. DWORD dwFlags,
  1276. DWORD dwHandleType,
  1277. IWmiDbSession **pSess)
  1278. {
  1279. HRESULT hr = WBEM_S_NO_ERROR;
  1280. _WMILockit lkt(&m_cs);
  1281. CWmiDbSession *pSession = NULL;
  1282. Sessions::iterator walk = m_Sessions.begin();
  1283. while (walk != m_Sessions.end())
  1284. {
  1285. pSession = *walk;
  1286. if (!(pSession)->m_bInUse)
  1287. {
  1288. (pSession)->m_bInUse = TRUE;
  1289. break;
  1290. }
  1291. walk++;
  1292. }
  1293. if (!pSession)
  1294. {
  1295. hr = SetConnProps(pLogon);
  1296. if (SUCCEEDED(hr))
  1297. {
  1298. pSession = new CWmiDbSession(this);
  1299. if (pSession)
  1300. {
  1301. (pSession)->m_bInUse = TRUE;
  1302. pSession->m_dwLocale = pLogon->pParm[4].Value.lVal;
  1303. m_Sessions.push_back(pSession);
  1304. pSession->m_pIMalloc = m_pIMalloc;
  1305. pSession->AddRef(); // For us
  1306. pSession->AddRef(); // For the end user.
  1307. *pSess = pSession;
  1308. }
  1309. else
  1310. hr = WBEM_E_OUT_OF_MEMORY;
  1311. }
  1312. }
  1313. else
  1314. {
  1315. hr = SetConnProps(pLogon);
  1316. pSession->m_dwLocale = pLogon->pParm[4].Value.lVal;
  1317. pSession->AddRef();
  1318. }
  1319. hr = ConnCache.SetCredentials(m_rgInitPropSet);
  1320. hr = ConnCache.SetMaxConnections (20);
  1321. hr = ConnCache.SetTimeoutSecs(60);
  1322. if (pLogon->pParm[3].Value.vt == VT_BSTR)
  1323. hr = ConnCache.SetDatabase(pLogon->pParm[3].Value.bstrVal);
  1324. else
  1325. hr = ConnCache.SetDatabase(L""); // This isn't a SQL db.
  1326. // Make sure the login credentials worked.
  1327. // If they specified "No initialization", they
  1328. // don't intend to use the database - they are
  1329. // probably going to perform a backup or restore.
  1330. if (!(dwFlags & WMIDB_FLAG_NO_INIT))
  1331. {
  1332. CSQLConnection *pConn;
  1333. hr = ConnCache.GetConnection(&pConn, FALSE, FALSE, 30);
  1334. if (SUCCEEDED(hr))
  1335. ConnCache.ReleaseConnection(pConn);
  1336. }
  1337. return hr;
  1338. }
  1339. //***************************************************************************
  1340. //
  1341. // CWmiDbController::SetConnProps
  1342. //
  1343. //***************************************************************************
  1344. HRESULT CWmiDbController::SetConnProps(WMIDB_LOGON_TEMPLATE *pLogon)
  1345. {
  1346. HRESULT hr = WBEM_S_NO_ERROR;
  1347. ULONG nProps = pLogon->dwArraySize + 2 ;
  1348. // This just sets the latest connection properties.
  1349. // MOVE ME: SQL Server-specific optimization.
  1350. // wchar_t wMachineName[MAX_COMPUTERNAME_LENGTH+1];
  1351. // DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  1352. // GetComputerName(wMachineName, &dwSize);
  1353. // if (!wcscmp(pLogon->pParm[0].strParmDisplayName, wMachineName))
  1354. // wcscpy(wMachineName, L".");
  1355. // else
  1356. // wcscpy(wMachineName, pLogon->pParm[0].Value.bstrVal);
  1357. if (!m_InitProperties)
  1358. {
  1359. m_InitProperties = new DBPROP[nProps];
  1360. if (!m_InitProperties)
  1361. return WBEM_E_OUT_OF_MEMORY;
  1362. m_rgInitPropSet = new DBPROPSET;
  1363. if (!m_rgInitPropSet)
  1364. {
  1365. delete m_InitProperties;
  1366. return WBEM_E_OUT_OF_MEMORY;
  1367. }
  1368. }
  1369. int i = 0;
  1370. m_InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED;
  1371. m_InitProperties[i].dwPropertyID = DBPROP_INIT_PROMPT;
  1372. m_InitProperties[i].vValue.vt = VT_I2;
  1373. m_InitProperties[i].vValue.iVal = DBPROMPT_NOPROMPT;
  1374. m_InitProperties[i].colid = DB_NULLID;
  1375. i++;
  1376. for (i = 1; i < (pLogon->dwArraySize + 1); i++ )
  1377. {
  1378. m_InitProperties[i].colid = DB_NULLID;
  1379. VariantInit(&m_InitProperties[i].vValue);
  1380. m_InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED;
  1381. m_InitProperties[i].dwPropertyID = pLogon->pParm[i-1].dwId;
  1382. m_InitProperties[i].vValue.vt = pLogon->pParm[i-1].Value.vt;
  1383. if (pLogon->pParm[i-1].Value.vt == VT_BSTR)
  1384. m_InitProperties[i].vValue.bstrVal = SysAllocString(pLogon->pParm[i-1].Value.bstrVal);
  1385. else if (pLogon->pParm[i-1].Value.vt == VT_I4)
  1386. m_InitProperties[i].vValue.lVal = pLogon->pParm[i-1].Value.lVal;
  1387. }
  1388. m_InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED;
  1389. m_InitProperties[i].colid = DB_NULLID;
  1390. m_InitProperties[i].dwPropertyID = DBPROP_INIT_TIMEOUT;
  1391. m_InitProperties[i].vValue.vt = VT_I4;
  1392. m_InitProperties[i].vValue.lVal = (long)m_dwTimeOut;
  1393. m_rgInitPropSet->guidPropertySet = DBPROPSET_DBINIT;
  1394. m_rgInitPropSet->cProperties = nProps;
  1395. m_rgInitPropSet->rgProperties = m_InitProperties;
  1396. return hr;
  1397. }
  1398. //***************************************************************************
  1399. //
  1400. // CWmiDbController::ReleaseSession
  1401. //
  1402. //***************************************************************************
  1403. HRESULT CWmiDbController::ReleaseSession(IWmiDbSession *pSession)
  1404. {
  1405. HRESULT hr = WBEM_S_NO_ERROR;
  1406. _WMILockit lkt(&m_cs);
  1407. // Mark connection unused and stick back in cache.
  1408. Sessions::iterator walk = m_Sessions.begin();
  1409. while (walk != m_Sessions.end())
  1410. {
  1411. CWmiDbSession *pConn2 = *walk;
  1412. if (pConn2 == ((CWmiDbSession *)pSession))
  1413. {
  1414. pConn2->m_bInUse = FALSE;
  1415. break;
  1416. }
  1417. }
  1418. return hr;
  1419. }
  1420. //***************************************************************************
  1421. //
  1422. // CWmiDbController::IncrementHitCount
  1423. //
  1424. //***************************************************************************
  1425. void CWmiDbController::IncrementHitCount (bool bCacheUsed)
  1426. {
  1427. _WMILockit lkt(&m_cs);
  1428. m_dwTotalHits++;
  1429. if (bCacheUsed)
  1430. m_dwCacheHits++;
  1431. }
  1432. //***************************************************************************
  1433. //
  1434. // CWmiDbController::AddHandle
  1435. //
  1436. //***************************************************************************
  1437. void CWmiDbController::AddHandle()
  1438. {
  1439. _WMILockit lkt(&m_cs);
  1440. m_dwTotalHandles++;
  1441. }
  1442. //***************************************************************************
  1443. //
  1444. // CWmiDbController::SubtractHandle
  1445. //
  1446. //***************************************************************************
  1447. void CWmiDbController::SubtractHandle()
  1448. {
  1449. _WMILockit lkt(&m_cs);
  1450. if (m_dwTotalHandles > 0)
  1451. m_dwTotalHandles--;
  1452. }
  1453. //***************************************************************************
  1454. //
  1455. // CWmiDbController::HasSecurityDescriptor
  1456. //
  1457. //***************************************************************************
  1458. BOOL CWmiDbController::HasSecurityDescriptor(SQL_ID ObjId)
  1459. {
  1460. BOOL bRet = FALSE;
  1461. _WMILockit _Lk(&m_cs);
  1462. SQL_IDMap::iterator it = SecuredIDs.find(ObjId);
  1463. if (it != SecuredIDs.end())
  1464. bRet = TRUE;
  1465. return bRet;
  1466. }
  1467. //***************************************************************************
  1468. //
  1469. // CWmiDbController::HasSecurityDescriptor
  1470. //
  1471. //***************************************************************************
  1472. void CWmiDbController::AddSecurityDescriptor(SQL_ID ObjId)
  1473. {
  1474. _WMILockit _Lk(&m_cs);
  1475. SecuredIDs[ObjId] = true;
  1476. }
  1477. //***************************************************************************
  1478. //
  1479. // CWmiDbController::HasSecurityDescriptor
  1480. //
  1481. //***************************************************************************
  1482. void CWmiDbController::RemoveSecurityDescriptor(SQL_ID ObjId)
  1483. {
  1484. _WMILockit _Lk(&m_cs);
  1485. SQL_IDMap::iterator it = SecuredIDs.find(ObjId);
  1486. if (it != SecuredIDs.end())
  1487. SecuredIDs.erase(it);
  1488. }
  1489. //***************************************************************************
  1490. //
  1491. // CWmiDbSession::CWmiDbSession
  1492. //
  1493. //***************************************************************************
  1494. CWmiDbSession::CWmiDbSession(IWmiDbController *pControl)
  1495. {
  1496. m_uRefCount = 0;
  1497. m_pController = pControl;
  1498. m_dwLocale = 0;
  1499. m_bInUse = false;
  1500. m_pIMalloc = NULL;
  1501. m_bIsDistributed = FALSE;
  1502. m_pController->AddRef();
  1503. }
  1504. //***************************************************************************
  1505. //
  1506. // CWmiDbSession::CWmiDbSession
  1507. //
  1508. //***************************************************************************
  1509. CWmiDbSession::~CWmiDbSession()
  1510. {
  1511. if (m_pController)
  1512. {
  1513. ((CWmiDbController *)m_pController)->ReleaseSession(this);
  1514. m_pController->Release();
  1515. }
  1516. if (m_pIMalloc)
  1517. m_pIMalloc->Release();
  1518. }
  1519. //***************************************************************************
  1520. //
  1521. // CWmiDbSession::QueryInterface
  1522. //
  1523. //***************************************************************************
  1524. HRESULT STDMETHODCALLTYPE CWmiDbSession::QueryInterface(
  1525. /* [in] */ REFIID riid,
  1526. /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
  1527. {
  1528. *ppvObject = 0;
  1529. if (IID_IUnknown==riid || IID_IWmiDbSession==riid )
  1530. {
  1531. *ppvObject = (IWmiDbSession*)this;
  1532. AddRef();
  1533. return S_OK;
  1534. }
  1535. else if (IID_IWmiDbBatchSession == riid)
  1536. {
  1537. *ppvObject = (IWmiDbBatchSession*)this;
  1538. AddRef();
  1539. return S_OK;
  1540. }
  1541. else if (IID_IWbemTransaction == riid)
  1542. {
  1543. *ppvObject = (IWbemTransaction*)this;
  1544. AddRef();
  1545. return S_OK;
  1546. }
  1547. else if (IID_IWmiDbBackupRestore == riid)
  1548. {
  1549. *ppvObject = (IWmiDbBackupRestore*)this;
  1550. AddRef();
  1551. return S_OK;
  1552. }
  1553. return E_NOINTERFACE;
  1554. }
  1555. //***************************************************************************
  1556. //
  1557. // CWmiDbSession::AddRef
  1558. //
  1559. //***************************************************************************
  1560. ULONG STDMETHODCALLTYPE CWmiDbSession::AddRef( )
  1561. {
  1562. InterlockedIncrement((LONG *) &m_uRefCount);
  1563. return m_uRefCount;
  1564. }
  1565. //***************************************************************************
  1566. //
  1567. // CWmiDbSession::Release
  1568. //
  1569. //***************************************************************************
  1570. ULONG STDMETHODCALLTYPE CWmiDbSession::Release( )
  1571. {
  1572. ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount);
  1573. if (0 != uNewCount)
  1574. return uNewCount;
  1575. delete this;
  1576. return WBEM_S_NO_ERROR;
  1577. }
  1578. //***************************************************************************
  1579. //
  1580. // CWmiDbSession::GetObject
  1581. //
  1582. //***************************************************************************
  1583. HRESULT STDMETHODCALLTYPE CWmiDbSession::GetObject(
  1584. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  1585. /* [in] */ IWbemPath __RPC_FAR *pPath,
  1586. /* [in] */ DWORD dwFlags,
  1587. /* [in] */ DWORD dwRequestedHandleType,
  1588. /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult)
  1589. {
  1590. HRESULT hr = WBEM_S_NO_ERROR;
  1591. // SYSTEMTIME tStartTime, tEndTime;
  1592. // GetLocalTime(&tStartTime);
  1593. // StartCAP();
  1594. if (!m_pController ||
  1595. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  1596. return WBEM_E_SHUTTING_DOWN;
  1597. if (!pScope
  1598. || !pPath
  1599. || dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID
  1600. || !ppResult
  1601. || (dwRequestedHandleType & ~WMIDB_HANDLE_TYPE_COOKIE
  1602. &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED
  1603. &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE
  1604. &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE
  1605. &~WMIDB_HANDLE_TYPE_SUBSCOPED &~WMIDB_HANDLE_TYPE_SCOPE
  1606. &~WMIDB_HANDLE_TYPE_CONTAINER))
  1607. return WBEM_E_INVALID_PARAMETER;
  1608. try
  1609. {
  1610. {
  1611. _WMILockit lkt(GetCS());
  1612. if (!((CWmiDbController *)m_pController)->m_bCacheInit)
  1613. {
  1614. hr = LoadSchemaCache();
  1615. if (SUCCEEDED(hr))
  1616. ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE;
  1617. else
  1618. return hr;
  1619. }
  1620. }
  1621. _bstr_t sNewPath;
  1622. SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  1623. if (SUCCEEDED(hr))
  1624. {
  1625. LPWSTR lpNewPath = NULL;
  1626. BOOL bStoreDefault = TRUE;
  1627. SQL_ID dStorageClassId = 0;
  1628. hr = NormalizeObjectPathGet(pScope, pPath, &lpNewPath, &bStoreDefault, &dStorageClassId, &dScopeId);
  1629. CDeleteMe <wchar_t> r(lpNewPath);
  1630. if (SUCCEEDED(hr))
  1631. {
  1632. if (bStoreDefault)
  1633. {
  1634. // Handle the __Instances container.
  1635. // since this is not a real object.
  1636. if (dStorageClassId == INSTANCESCLASSID)
  1637. {
  1638. if (((dwRequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_COOKIE &&
  1639. (dwRequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_VERSIONED) ||
  1640. !bStoreDefault)
  1641. hr = WBEM_E_INVALID_PARAMETER;
  1642. else
  1643. {
  1644. SQL_ID dScopeId2 = dScopeId;
  1645. hr = GetObject_Internal(L"__Instances", dwFlags, dwRequestedHandleType,
  1646. &dScopeId2, ppResult);
  1647. if (SUCCEEDED(hr))
  1648. {
  1649. SQL_ID dClassId;
  1650. hr = GetSchemaCache()->GetClassID(lpNewPath, dScopeId, dClassId);
  1651. if (SUCCEEDED(hr))
  1652. {
  1653. CWmiDbHandle *pTemp = (CWmiDbHandle *)*ppResult;
  1654. pTemp->m_dObjectId = dClassId;
  1655. pTemp->m_dClassId = INSTANCESCLASSID;
  1656. pTemp->m_dScopeId = dScopeId;
  1657. }
  1658. }
  1659. }
  1660. }
  1661. else
  1662. hr = GetObject_Internal(lpNewPath, dwFlags, dwRequestedHandleType, &dScopeId, ppResult);
  1663. if (SUCCEEDED(hr))
  1664. {
  1665. // Mark this object as "custom" if
  1666. // this is a descendant of a custom scope,
  1667. // or if this is a custom namespace.
  1668. CWmiDbHandle *pTemp = (CWmiDbHandle *)*ppResult;
  1669. pTemp->m_bDefault = ((CWmiDbHandle *)pScope)->m_bDefault;
  1670. if (pTemp->m_dClassId == MAPPEDNSCLASSID)
  1671. pTemp->m_bDefault = FALSE;
  1672. }
  1673. }
  1674. // Use the custom storage mechanism.
  1675. else
  1676. {
  1677. // This needs to take care of all security and locks!!
  1678. hr = CustomGetObject(pScope, pPath, lpNewPath, dwFlags, dwRequestedHandleType, ppResult);
  1679. }
  1680. // GetLocalTime(&tEndTime);
  1681. // ERRORTRACE((LOG_WBEMCORE, "IWmiDbSession::GetObject (%S) - %ld ms\n", lpNewPath, GetDiff(tEndTime, tStartTime)));
  1682. }
  1683. }
  1684. }
  1685. catch (...)
  1686. {
  1687. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::GetObject\n"));
  1688. hr = WBEM_E_CRITICAL_ERROR;
  1689. }
  1690. // StopCAP();
  1691. return hr;
  1692. }
  1693. //***************************************************************************
  1694. //
  1695. // CWmiDbSession::GetObjectDirect
  1696. //
  1697. //***************************************************************************
  1698. HRESULT STDMETHODCALLTYPE CWmiDbSession::GetObjectDirect(
  1699. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  1700. /* [in] */ IWbemPath __RPC_FAR *pPath,
  1701. /* [in] */ DWORD dwFlags,
  1702. /* [in] */ REFIID riid,
  1703. /* [iid_is][out] */ LPVOID __RPC_FAR *pObj)
  1704. {
  1705. HRESULT hr = WBEM_S_NO_ERROR;
  1706. try
  1707. {
  1708. if (!m_pController ||
  1709. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  1710. return WBEM_E_SHUTTING_DOWN;
  1711. IWmiDbHandle *pHandle= NULL;
  1712. CSQLConnection *pConn = NULL;
  1713. hr = GetSQLCache()->GetConnection(&pConn, FALSE, IsDistributed());
  1714. if (SUCCEEDED(hr))
  1715. {
  1716. LPWSTR lpNewPath = NULL;
  1717. BOOL bStoreDefault = TRUE;
  1718. SQL_ID dStorageClassId = 0;
  1719. SQL_ID dScopeId;
  1720. IWmiDbHandle *pHandle = NULL;
  1721. hr = NormalizeObjectPathGet(pScope, pPath, &lpNewPath, &bStoreDefault, &dStorageClassId, &dScopeId, pConn);
  1722. CDeleteMe <wchar_t> r(lpNewPath);
  1723. if (!bStoreDefault || (dStorageClassId == INSTANCESCLASSID))
  1724. hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE, &pHandle);
  1725. else if (SUCCEEDED(hr))
  1726. hr = GetObject_Internal(lpNewPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE, &dScopeId, &pHandle, pConn);
  1727. if (SUCCEEDED(hr))
  1728. {
  1729. CReleaseMe r (pHandle);
  1730. hr = ((CWmiDbHandle *)pHandle)->QueryInterface_Internal(pConn, pObj);
  1731. }
  1732. GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
  1733. }
  1734. }
  1735. catch (...)
  1736. {
  1737. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::GetObjectDirect\n"));
  1738. hr = WBEM_E_CRITICAL_ERROR;
  1739. }
  1740. return hr;
  1741. }
  1742. //***************************************************************************
  1743. //
  1744. // CWmiDbSession::GetObject
  1745. //
  1746. //***************************************************************************
  1747. HRESULT STDMETHODCALLTYPE CWmiDbSession::GetObject_Internal(
  1748. /* [in] */ LPWSTR lpPath, /* The full path */
  1749. /* [in] */ DWORD dwFlags,
  1750. /* [in] */ DWORD dwRequestedHandleType,
  1751. /* [in] */ SQL_ID *pScopeId,
  1752. /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult,
  1753. CSQLConnection *pConn)
  1754. {
  1755. HRESULT hr = WBEM_S_NO_ERROR;
  1756. bool bImmediate = !(dwRequestedHandleType & WMIDB_HANDLE_TYPE_SUBSCOPED);
  1757. SQL_ID dScopeId = 0;
  1758. if (pScopeId)
  1759. dScopeId = *pScopeId;
  1760. if (!m_pController ||
  1761. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  1762. return WBEM_E_SHUTTING_DOWN;
  1763. if (!lpPath)
  1764. return WBEM_E_INVALID_PARAMETER;
  1765. *ppResult = NULL;
  1766. SQL_ID dObjId = 0, dClassId = 0;
  1767. LPWSTR lpKey = GetKeyString(lpPath);
  1768. CDeleteMe <wchar_t> r(lpKey);
  1769. BOOL bGetScope = FALSE;
  1770. BOOL bNeedToRelease = FALSE;
  1771. if (!pConn)
  1772. {
  1773. hr = GetSQLCache()->GetConnection(&pConn, FALSE, IsDistributed());
  1774. bNeedToRelease = TRUE;
  1775. if (FAILED(hr))
  1776. return hr;
  1777. }
  1778. // Special-case: Go up to the previous scope
  1779. if (!wcscmp(lpPath, L".."))
  1780. {
  1781. hr = GetSchemaCache()->GetParentNamespace(dScopeId, dObjId, &dClassId);
  1782. if (FAILED(hr))
  1783. {
  1784. BOOL bExists = FALSE;
  1785. hr = GetObjectCache()->GetObject(dScopeId, NULL, &dObjId);
  1786. if (FAILED(hr))
  1787. bGetScope = TRUE;
  1788. else
  1789. hr = CSQLExecProcedure::ObjectExists(pConn, dObjId, bExists, &dClassId, NULL);
  1790. }
  1791. }
  1792. else
  1793. hr = GetObjectCache()->GetObjectId(lpKey, dObjId, dClassId, &dScopeId);
  1794. if (FAILED(hr))
  1795. {
  1796. hr = WBEM_S_NO_ERROR;
  1797. if (SUCCEEDED(hr))
  1798. {
  1799. BOOL bExists = FALSE;
  1800. if (!bGetScope)
  1801. {
  1802. hr = CSQLExecProcedure::ObjectExists(pConn, dObjId, bExists, &dClassId, &dScopeId);
  1803. if (hr == E_NOTIMPL)
  1804. {
  1805. hr = CSQLExecProcedure::GetObjectIdByPath(pConn, lpKey, dObjId, dClassId, &dScopeId);
  1806. if (dObjId)
  1807. bExists = TRUE;
  1808. }
  1809. }
  1810. else
  1811. {
  1812. // If we are getting the parent object,
  1813. // hit the db again to find the essentials there.
  1814. hr = CSQLExecProcedure::ObjectExists(pConn, dScopeId, bExists, &dClassId, &dObjId);
  1815. if (SUCCEEDED(hr))
  1816. hr = CSQLExecProcedure::ObjectExists(pConn, dObjId, bExists, &dClassId, &dScopeId);
  1817. }
  1818. if (SUCCEEDED(hr) && bExists)
  1819. {
  1820. // If a cookie or protected handle, just ref count.
  1821. // If exclusive, there can be only one.
  1822. // If versioned, we need to keep each version separate.
  1823. if ((dwRequestedHandleType & 0xF) == WMIDB_HANDLE_TYPE_COOKIE ||
  1824. (dwRequestedHandleType & 0xF) == WMIDB_HANDLE_TYPE_PROTECTED)
  1825. ((CWmiDbController *)m_pController)->LockCache.GetHandle(dObjId, dwRequestedHandleType, ppResult);
  1826. if (*ppResult == NULL)
  1827. {
  1828. // If this object exists, try and obtain the requested lock.
  1829. CWmiDbHandle *pTemp = new CWmiDbHandle;
  1830. if (pTemp)
  1831. {
  1832. DWORD dwVersion = 0;
  1833. pTemp->m_pSession = this;
  1834. AddRef_Lock();
  1835. // If this is a class, we want to lock its parents.
  1836. if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  1837. {
  1838. DWORD dwReq = WBEM_ENABLE;
  1839. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  1840. dwReq |= READ_CONTROL;
  1841. hr = VerifyObjectSecurity(pConn, dObjId, dClassId, dScopeId, 0, dwReq);
  1842. }
  1843. if (SUCCEEDED(hr))
  1844. {
  1845. if (IsDistributed())
  1846. {
  1847. // Does this lock exist locally?
  1848. hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(false, dObjId,
  1849. WMIDB_HANDLE_TYPE_PROTECTED, pTemp, dScopeId, dClassId,
  1850. &((CWmiDbController *)m_pController)->SchemaCache, false, 0, 0, &dwVersion);
  1851. if (FAILED(hr))
  1852. {
  1853. // OK if the lock has already been taken
  1854. // on this session...
  1855. if (LockExists(dObjId))
  1856. hr = WBEM_S_NO_ERROR;
  1857. }
  1858. if (SUCCEEDED(hr))
  1859. hr = AddTransLock(dObjId, WMIDB_HANDLE_TYPE_PROTECTED);
  1860. }
  1861. if (SUCCEEDED(hr))
  1862. {
  1863. hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjId, dwRequestedHandleType, pTemp,
  1864. dScopeId, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, false, 0, 0, &dwVersion);
  1865. }
  1866. }
  1867. if (FAILED(hr))
  1868. {
  1869. delete pTemp;
  1870. *ppResult = NULL;
  1871. }
  1872. else
  1873. {
  1874. // We have the lock. They will have to call Release() to
  1875. // free it up.
  1876. ((CWmiDbController *)m_pController)->AddHandle();
  1877. pTemp->AddRef();
  1878. pTemp->m_dwHandleType = dwRequestedHandleType;
  1879. pTemp->m_dObjectId = dObjId;
  1880. pTemp->m_bDefault = TRUE;
  1881. pTemp->m_dClassId = dClassId;
  1882. pTemp->m_dScopeId = dScopeId;
  1883. pTemp->m_dwVersion = dwVersion;
  1884. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  1885. pTemp->m_bSecDesc = TRUE;
  1886. if (ppResult)
  1887. *ppResult = pTemp;
  1888. }
  1889. }
  1890. else
  1891. {
  1892. if (ppResult)
  1893. *ppResult = NULL;
  1894. hr = WBEM_E_OUT_OF_MEMORY;
  1895. }
  1896. if (m_pController)
  1897. ((CWmiDbController *)m_pController)->IncrementHitCount(false);
  1898. }
  1899. }
  1900. else if (SUCCEEDED(hr))
  1901. hr = WBEM_E_NOT_FOUND;
  1902. }
  1903. }
  1904. else
  1905. {
  1906. if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  1907. {
  1908. DWORD dwReq = WBEM_ENABLE;
  1909. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  1910. dwReq |= READ_CONTROL;
  1911. hr = VerifyObjectSecurity(pConn, dObjId, dClassId, dScopeId, 0, dwReq);
  1912. }
  1913. if (SUCCEEDED(hr))
  1914. {
  1915. // At this point, we know that the object has been
  1916. // cached. Try to obtain a lock.
  1917. // ===============================================
  1918. CWmiDbHandle *pTemp = new CWmiDbHandle;
  1919. if (pTemp)
  1920. {
  1921. DWORD dwVersion = 0;
  1922. pTemp->m_pSession = this;
  1923. hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjId, dwRequestedHandleType, pTemp,
  1924. dScopeId, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, false, 0, 0, &dwVersion);
  1925. if (SUCCEEDED(hr))
  1926. {
  1927. AddRef_Lock();
  1928. ((CWmiDbController *)m_pController)->AddHandle();
  1929. pTemp->AddRef();
  1930. pTemp->m_dwHandleType = dwRequestedHandleType;
  1931. pTemp->m_dObjectId = dObjId;
  1932. pTemp->m_bDefault = TRUE;
  1933. pTemp->m_dClassId = dClassId;
  1934. pTemp->m_dScopeId = dScopeId;
  1935. pTemp->m_dwVersion = dwVersion;
  1936. pTemp->m_pData = NULL;
  1937. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  1938. pTemp->m_bSecDesc = TRUE;
  1939. if (ppResult)
  1940. *ppResult = pTemp;
  1941. // We won't bother attaching the object part until they
  1942. // ask for it.
  1943. }
  1944. else
  1945. {
  1946. delete pTemp;
  1947. *ppResult = NULL;
  1948. }
  1949. }
  1950. else
  1951. {
  1952. hr = WBEM_E_OUT_OF_MEMORY;
  1953. }
  1954. }
  1955. if (m_pController)
  1956. ((CWmiDbController *)m_pController)->IncrementHitCount(true);
  1957. }
  1958. if (bNeedToRelease)
  1959. GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
  1960. if (pScopeId)
  1961. *pScopeId = dScopeId;
  1962. return hr;
  1963. }
  1964. //***************************************************************************
  1965. //
  1966. // CWmiDbSession::PutObject
  1967. //
  1968. //***************************************************************************
  1969. HRESULT STDMETHODCALLTYPE CWmiDbSession::PutObject(
  1970. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  1971. /* [in] */ REFIID riid,
  1972. /* [iid_is][in] */ LPVOID pObjToPut,
  1973. /* [in] */ DWORD dwFlags,
  1974. /* [in] */ DWORD dwRequestedHandleType,
  1975. /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult)
  1976. {
  1977. HRESULT hr = 0;
  1978. CSQLConnection *pConn = NULL;
  1979. AddRef_Lock();
  1980. // StartCAP();
  1981. //SYSTEMTIME tStartTime, tEndTime;
  1982. //GetLocalTime(&tStartTime);
  1983. if (!m_pController ||
  1984. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  1985. return WBEM_E_SHUTTING_DOWN;
  1986. if (dwFlags & ~WBEM_FLAG_CREATE_ONLY & ~WBEM_FLAG_UPDATE_ONLY & ~WBEM_FLAG_CREATE_OR_UPDATE
  1987. & ~WMIDB_DISABLE_EVENTS & ~WBEM_FLAG_USE_SECURITY_DESCRIPTOR &~ WBEM_FLAG_REMOVE_CHILD_SECURITY
  1988. & ~WMIDB_FLAG_ADMIN_VERIFIED &~ WBEM_FLAG_UPDATE_SAFE_MODE &~ WBEM_FLAG_UPDATE_FORCE_MODE)
  1989. return WBEM_E_INVALID_PARAMETER;
  1990. if ((ppResult && (dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID))
  1991. || !pScope
  1992. || !pObjToPut)
  1993. return WBEM_E_INVALID_PARAMETER;
  1994. if (riid != IID_IWbemClassObject &&
  1995. riid != IID_IWmiDbHandle &&
  1996. riid != IID__IWmiObject)
  1997. return WBEM_E_NOT_SUPPORTED;
  1998. try
  1999. {
  2000. {
  2001. _WMILockit lkt(GetCS());
  2002. if (!((CWmiDbController *)m_pController)->m_bCacheInit)
  2003. {
  2004. hr = LoadSchemaCache();
  2005. if (SUCCEEDED(hr))
  2006. ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE;
  2007. else
  2008. return hr;
  2009. }
  2010. }
  2011. hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed());
  2012. if (SUCCEEDED(hr))
  2013. {
  2014. _bstr_t sWaste = L"";
  2015. BOOL bSys = FALSE;
  2016. hr = PutObject(pConn, pScope, 0, L"", (IUnknown *)pObjToPut, dwFlags, dwRequestedHandleType, sWaste, ppResult);
  2017. if (SUCCEEDED(hr) && ppResult)
  2018. {
  2019. CWmiDbHandle *pTemp = (CWmiDbHandle *)*ppResult;
  2020. pTemp->m_bDefault = ((CWmiDbHandle *)pScope)->m_bDefault;
  2021. if (pTemp->m_dClassId == MAPPEDNSCLASSID)
  2022. pTemp->m_bDefault = FALSE;
  2023. }
  2024. GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
  2025. if (!(dwFlags & WMIDB_DISABLE_EVENTS) && !IsDistributed())
  2026. {
  2027. if (SUCCEEDED(hr))
  2028. ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath);
  2029. }
  2030. }
  2031. }
  2032. catch (...)
  2033. {
  2034. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::PutObject\n"));
  2035. hr = WBEM_E_CRITICAL_ERROR;
  2036. }
  2037. // StopCAP();
  2038. UnlockDynasties();
  2039. return hr;
  2040. }
  2041. //***************************************************************************
  2042. //
  2043. // CWmiDbSession::PutObject
  2044. //
  2045. //***************************************************************************
  2046. HRESULT STDMETHODCALLTYPE CWmiDbSession::PutObject(
  2047. CSQLConnection *pConn,
  2048. IWmiDbHandle __RPC_FAR *pScope,
  2049. SQL_ID dScopeID,
  2050. LPWSTR lpScopePath,
  2051. /* [in] */ IUnknown __RPC_FAR *pObjToPut,
  2052. /* [in] */ DWORD dwFlags,
  2053. /* [in] */ DWORD dwRequestedHandleType,
  2054. _bstr_t &sPath,
  2055. /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult,
  2056. BOOL bStoreAsClass )
  2057. {
  2058. HRESULT hr = WBEM_S_NO_ERROR;
  2059. SQL_ID dObjectId = 0;
  2060. IWmiDbHandle *pHandle = NULL;
  2061. bool bClass = false, bLockVerified = false;
  2062. if (!m_pController ||
  2063. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  2064. return WBEM_E_SHUTTING_DOWN;
  2065. if ((dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID) && ppResult)
  2066. return WBEM_E_INVALID_PARAMETER;
  2067. if (dwRequestedHandleType & ~WMIDB_HANDLE_TYPE_COOKIE
  2068. &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED
  2069. &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE
  2070. &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE
  2071. &~WMIDB_HANDLE_TYPE_SUBSCOPED&~WMIDB_HANDLE_TYPE_AUTODELETE
  2072. &~WMIDB_HANDLE_TYPE_CONTAINER &~ WMIDB_HANDLE_TYPE_SCOPE )
  2073. return WBEM_E_INVALID_PARAMETER;
  2074. bool bImmediate = !(dwRequestedHandleType & WMIDB_HANDLE_TYPE_SUBSCOPED);
  2075. SQL_ID dClassId = 0;
  2076. // Hand this to the repository, to ensure that it cleans up
  2077. // any autodelete objects on failure.
  2078. dwFlags |= (dwRequestedHandleType & WMIDB_HANDLE_TYPE_AUTODELETE);
  2079. if (!m_pController ||
  2080. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  2081. return WBEM_E_SHUTTING_DOWN;
  2082. // Normalize the object path.
  2083. sPath = L"";
  2084. BOOL bStoreDefault = TRUE;
  2085. IWbemClassObject *pOutObj = NULL;
  2086. LPWSTR lpScope = NULL;
  2087. if (pScope)
  2088. {
  2089. if (GetSchemaCache()->IsDerivedClass
  2090. (INSTANCESCLASSID, ((CWmiDbHandle *)pScope)->m_dClassId) ||
  2091. ((CWmiDbHandle *)pScope)->m_dClassId == INSTANCESCLASSID)
  2092. hr = WBEM_E_INVALID_OPERATION;
  2093. else
  2094. {
  2095. CWbemClassObjectProps *pProps= NULL;
  2096. hr = NormalizeObjectPath(pScope, (LPWSTR)NULL, &lpScope, FALSE, &pProps, &bStoreDefault, pConn);
  2097. CDeleteMe <CWbemClassObjectProps> r (pProps);
  2098. dScopeID = ((CWmiDbHandle *)pScope)->m_dObjectId;
  2099. if (SUCCEEDED(hr) && dScopeID)
  2100. {
  2101. SQL_ID dParent = 0;
  2102. LPWSTR lpScopeKey = GetKeyString(lpScope);
  2103. CDeleteMe <wchar_t> r1 (lpScopeKey);
  2104. if (FAILED(GetSchemaCache()->GetNamespaceID(lpScopeKey, dParent)))
  2105. {
  2106. if (pProps)
  2107. {
  2108. DWORD dwTempHandle = ((CWmiDbHandle *)pScope)->m_dwHandleType;
  2109. ((CWmiDbHandle *)pScope)->m_dwHandleType |= WMIDB_HANDLE_TYPE_STRONG_CACHE;
  2110. IWbemClassObject *pObj = NULL;
  2111. hr = ((CWmiDbHandle *)pScope)->QueryInterface_Internal(pConn, (void **)&pObj);
  2112. CReleaseMe r (pObj);
  2113. ((CWmiDbHandle *)pScope)->m_dwHandleType = dwTempHandle;
  2114. if (SUCCEEDED(hr))
  2115. {
  2116. if (pProps->lpNamespace && wcslen(pProps->lpNamespace))
  2117. GetSchemaCache()->GetNamespaceID(pProps->lpNamespace, dParent);
  2118. hr = GetSchemaCache()->AddNamespace(lpScope, lpScopeKey, dScopeID, dParent,
  2119. ((CWmiDbHandle *)pScope)->m_dClassId);
  2120. CSQLExecProcedure::InsertScopeMap(pConn, dScopeID, lpScopeKey, dParent);
  2121. }
  2122. }
  2123. else if (lpScope && wcslen(lpScope))
  2124. {
  2125. delete lpScope;
  2126. return WBEM_E_INVALID_OPERATION;
  2127. }
  2128. }
  2129. }
  2130. }
  2131. if (SUCCEEDED(hr) && !dScopeID)
  2132. hr = WBEM_E_INVALID_OBJECT;
  2133. }
  2134. else if (lpScopePath != NULL)
  2135. {
  2136. lpScope = new wchar_t [wcslen(lpScopePath) + 1];
  2137. if (!lpScope)
  2138. return WBEM_E_OUT_OF_MEMORY;
  2139. wcscpy(lpScope, lpScopePath);
  2140. }
  2141. CDeleteMe <wchar_t> r (lpScope);
  2142. // Validate that this object has permission to
  2143. // write this object, and the handle is not out of date.
  2144. // =====================================================
  2145. if (SUCCEEDED(hr))
  2146. {
  2147. hr = pObjToPut->QueryInterface(IID_IWmiDbHandle, (void **)&pHandle);
  2148. CReleaseMe rHandle (pHandle);
  2149. if (SUCCEEDED(hr))
  2150. {
  2151. CWmiDbHandle *pTemp = (CWmiDbHandle *)pHandle;
  2152. dObjectId = pTemp->m_dObjectId;
  2153. // If they took out a protected lock,
  2154. // they can't modify it either.
  2155. // =================================
  2156. if (pTemp->m_dwHandleType == WMIDB_HANDLE_TYPE_PROTECTED)
  2157. hr = WBEM_E_ACCESS_DENIED;
  2158. else
  2159. {
  2160. hr = VerifyObjectLock(dObjectId, pTemp->m_dwHandleType, pTemp->m_dwVersion);
  2161. if (SUCCEEDED(hr))
  2162. {
  2163. bLockVerified = true;
  2164. }
  2165. }
  2166. }
  2167. else
  2168. {
  2169. dObjectId = 0;
  2170. bLockVerified = 0;
  2171. hr = 0;
  2172. }
  2173. if (SUCCEEDED(hr))
  2174. {
  2175. // Get the IWbemClassobject interface. If none, fail.
  2176. IWbemClassObject *pObj = NULL;
  2177. bool bClass = false;
  2178. hr = pObjToPut->QueryInterface(IID_IWbemClassObject, (void **)&pObj);
  2179. CReleaseMe r2 (pObj);
  2180. if (SUCCEEDED(hr))
  2181. {
  2182. VARIANT vTemp;
  2183. VariantInit(&vTemp);
  2184. CClearMe c (&vTemp);
  2185. CWbemClassObjectProps objprops (this, pConn, pObj, &((CWmiDbController *)m_pController)->SchemaCache, dScopeID);
  2186. if (!objprops.lpClassName)
  2187. {
  2188. hr = WBEM_E_INVALID_OBJECT;
  2189. goto Exit;
  2190. }
  2191. BOOL bNs = FALSE;
  2192. if (IsDerivedFrom(pObj, L"__Instances"))
  2193. {
  2194. hr = WBEM_E_INVALID_OPERATION;
  2195. }
  2196. else
  2197. {
  2198. if (objprops.dwGenus == 1 || bStoreAsClass)
  2199. bClass = true;
  2200. if (pScope)
  2201. {
  2202. SQL_ID dId = ((CWmiDbHandle *)pScope)->m_dClassId;
  2203. if (objprops.lpClassName && wcslen(objprops.lpClassName) >=2)
  2204. {
  2205. if (objprops.lpClassName[0] == L'_' && objprops.lpClassName[1] == L'_')
  2206. {
  2207. bStoreDefault = TRUE;
  2208. if (objprops.dwGenus == 1)
  2209. {
  2210. dScopeID = 0;
  2211. lpScope = NULL;
  2212. }
  2213. }
  2214. else if (dId == MAPPEDNSCLASSID)
  2215. bStoreDefault = FALSE;
  2216. }
  2217. }
  2218. if (objprops.dwGenus == 2 &&
  2219. IsDerivedFrom(pObj, L"__Namespace"))
  2220. {
  2221. delete objprops.lpRelPath;
  2222. objprops.lpRelPath = GetPropertyVal(L"Name", pObj);
  2223. if (!objprops.lpRelPath)
  2224. {
  2225. hr = WBEM_E_OUT_OF_MEMORY;
  2226. goto Exit;
  2227. }
  2228. bNs = TRUE;
  2229. }
  2230. if (lpScope && dScopeID != ROOTNAMESPACEID)
  2231. {
  2232. if (!wcslen(lpScope))
  2233. {
  2234. ERRORTRACE((LOG_WBEMCORE, "Invalid scope text in CWmiDbSession::PutObject (%I64d) \n", dScopeID));
  2235. hr = WBEM_E_INVALID_PARAMETER;
  2236. goto Exit;
  2237. }
  2238. LPWSTR lpPath = NULL, lpPtr = NULL;
  2239. int iLen = wcslen(lpScope);
  2240. if (objprops.lpRelPath)
  2241. {
  2242. if (_wcsnicmp(objprops.lpRelPath, lpScope, iLen) ||
  2243. ((wcslen(objprops.lpRelPath) > iLen) &&
  2244. objprops.lpRelPath[iLen] != L'\\'))
  2245. {
  2246. lpPtr = new wchar_t [wcslen(objprops.lpRelPath) + wcslen(lpScope) + 10];
  2247. if (!lpPtr)
  2248. {
  2249. hr = WBEM_E_OUT_OF_MEMORY;
  2250. goto Exit;
  2251. }
  2252. lpPath = lpPtr;
  2253. if (!bNs)
  2254. swprintf(lpPath, L"%s:%s", lpScope, objprops.lpRelPath);
  2255. else
  2256. swprintf(lpPath, L"%s\\%s", lpScope, objprops.lpRelPath);
  2257. if (!_wcsnicmp(lpPath, L"root", wcslen(L"root")))
  2258. lpPtr += wcslen(L"root")+1;
  2259. sPath = lpPtr;
  2260. }
  2261. else
  2262. sPath += objprops.lpRelPath;
  2263. }
  2264. CDeleteMe <wchar_t> r4 (lpPath);
  2265. }
  2266. else
  2267. {
  2268. if (objprops.lpRelPath)
  2269. {
  2270. sPath += objprops.lpRelPath;
  2271. }
  2272. }
  2273. }
  2274. if (wcslen(objprops.lpClassName) > REPDRVR_NAME_LIMIT)
  2275. hr = WBEM_E_CLASS_NAME_TOO_WIDE;
  2276. else
  2277. objprops.lpKeyString = GetKeyString(sPath);
  2278. if (dScopeID)
  2279. {
  2280. //hr = VerifyObjectSecurity(pConn, dObjectId, dClassId, dScopeID, 0, dwRequired);
  2281. if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  2282. hr = VerifyObjectSecurity(pConn, dScopeID, 0, sPath, &objprops, dwRequestedHandleType, WBEM_PARTIAL_WRITE_REP, dObjectId, dClassId);
  2283. else
  2284. hr = VerifyObjectSecurity(pConn, dScopeID, 0, sPath, &objprops, dwRequestedHandleType, 0, dObjectId, dClassId);
  2285. }
  2286. if (SUCCEEDED(hr))
  2287. {
  2288. bool bChanged = false;
  2289. bool bNew = false;
  2290. if (bClass)
  2291. {
  2292. SQL_ID dTemp = 0;
  2293. if (FAILED(GetSchemaCache()->GetClassID(objprops.lpClassName, dScopeID, dTemp)))
  2294. bNew = true;
  2295. BOOL bIgnoreDefaults = (bStoreAsClass ? TRUE: FALSE);
  2296. hr = PutClass(pConn, dScopeID, lpScope, &objprops, pObj, dwFlags, dObjectId, sPath, bChanged, bIgnoreDefaults);
  2297. dClassId = 1;
  2298. // After we have put the class, *then*
  2299. // we see if we need to set it up in the
  2300. // custom database.
  2301. if (!bStoreDefault && SUCCEEDED(hr))
  2302. {
  2303. // Update the mapping for this class.
  2304. hr = CustomCreateMapping(pConn, objprops.lpClassName, pObj, pScope);
  2305. }
  2306. }
  2307. else if (dClassId)
  2308. {
  2309. // If this is a custom repository,
  2310. // forward this request to the custom rep code.
  2311. if (bStoreDefault)
  2312. {
  2313. hr = PutInstance(pConn, pScope, dScopeID, lpScope, &objprops, pObj, dwFlags, dObjectId, dClassId, sPath, bChanged);
  2314. }
  2315. else
  2316. {
  2317. hr = CustomPutInstance(pConn, pScope, dClassId, dwFlags, &pObj);
  2318. pOutObj = pObj;
  2319. }
  2320. }
  2321. else
  2322. hr = WBEM_E_INVALID_CLASS;
  2323. if (SUCCEEDED(hr))
  2324. {
  2325. if (SUCCEEDED(hr))
  2326. {
  2327. // Render return handle as needed.
  2328. if (ppResult)
  2329. {
  2330. if (pHandle)
  2331. {
  2332. pHandle->AddRef();
  2333. *ppResult = pHandle;
  2334. // Bump up version number, so other outstanding handles
  2335. // know this object changed.
  2336. hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjectId, WMIDB_HANDLE_TYPE_VERSIONED, NULL,
  2337. dScopeID, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, true, 0, 0);
  2338. if (SUCCEEDED(hr))
  2339. hr = ((CWmiDbController *)m_pController)->LockCache.DeleteLock(dObjectId, false, WMIDB_HANDLE_TYPE_VERSIONED, true, NULL);
  2340. }
  2341. else
  2342. {
  2343. DWORD dwVersion = 0;
  2344. CWmiDbHandle *pTemp = new CWmiDbHandle;
  2345. if (!pTemp)
  2346. {
  2347. hr = WBEM_E_OUT_OF_MEMORY;
  2348. goto Exit;
  2349. }
  2350. pTemp->m_pSession = this;
  2351. hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjectId, dwRequestedHandleType, pTemp,
  2352. dScopeID, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, true, 0, 0, &dwVersion);
  2353. if (SUCCEEDED(hr))
  2354. {
  2355. AddRef_Lock();
  2356. ((CWmiDbController *)m_pController)->AddHandle();
  2357. pTemp->m_dObjectId = dObjectId;
  2358. pTemp->m_dClassId = dClassId;
  2359. pTemp->m_bDefault = TRUE;
  2360. pTemp->m_dScopeId = dScopeID;
  2361. pTemp->m_pSession = this;
  2362. pTemp->m_pData = pOutObj;
  2363. if (pOutObj)
  2364. pOutObj->AddRef();
  2365. pTemp->AddRef();
  2366. pTemp->m_dwVersion = dwVersion;
  2367. pTemp->m_dwHandleType = dwRequestedHandleType;
  2368. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  2369. pTemp->m_bSecDesc = TRUE;
  2370. *ppResult = pTemp;
  2371. }
  2372. else
  2373. {
  2374. *ppResult = NULL;
  2375. delete pTemp;
  2376. }
  2377. }
  2378. }
  2379. else
  2380. {
  2381. // Bump up version number, so other outstanding handles
  2382. // know this object changed.
  2383. hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjectId, WMIDB_HANDLE_TYPE_VERSIONED, NULL,
  2384. dScopeID, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, true, 0, 0);
  2385. ((CWmiDbController *)m_pController)->LockCache.DeleteLock(dObjectId, false, WMIDB_HANDLE_TYPE_VERSIONED, true, NULL);
  2386. }
  2387. // Add an exclusive lock on this object...
  2388. // If cannot lock, check locally and see if we have one.
  2389. if (IsDistributed())
  2390. {
  2391. hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(false, dObjectId,
  2392. WMIDB_HANDLE_TYPE_EXCLUSIVE, NULL, dScopeID, dClassId,
  2393. &((CWmiDbController *)m_pController)->SchemaCache, true, 0, 0);
  2394. if (FAILED(hr))
  2395. {
  2396. if (LockExists(dObjectId))
  2397. hr = WBEM_S_NO_ERROR;
  2398. }
  2399. if (SUCCEEDED(hr))
  2400. {
  2401. hr = AddTransLock(dObjectId, WMIDB_HANDLE_TYPE_EXCLUSIVE);
  2402. }
  2403. }
  2404. // Update the object in the cache if necessary
  2405. // Either they want it cached now, or the
  2406. // object already exists in the cache.
  2407. // ===========================================
  2408. if (SUCCEEDED(hr))
  2409. {
  2410. if (GetObjectCache()->ObjectExists(dObjectId) ||
  2411. (dwRequestedHandleType & 0xF00) == WMIDB_HANDLE_TYPE_WEAK_CACHE ||
  2412. (dwRequestedHandleType & 0xF00) == WMIDB_HANDLE_TYPE_STRONG_CACHE)
  2413. {
  2414. bool bCacheType = ((dwRequestedHandleType & 0xF00) == WMIDB_HANDLE_TYPE_STRONG_CACHE) ? 1 : 0;
  2415. LPWSTR lpKey = GetKeyString(sPath);
  2416. CDeleteMe <wchar_t> r6(lpKey);
  2417. GetObjectCache()->PutObject(dObjectId, dClassId, dScopeID, lpKey, bCacheType, pObj);
  2418. }
  2419. // Regardless, if we have updated a class,
  2420. // we need to remove the instances
  2421. // and subclasses from the cache.
  2422. // ================================
  2423. if (bClass && !bNew)
  2424. {
  2425. SQL_ID dObjId = 0, dClassId = 0;
  2426. HRESULT hTemp = GetObjectCache()->FindFirst(dObjId, dClassId);
  2427. while (SUCCEEDED(hTemp))
  2428. {
  2429. if (dClassId == 1)
  2430. dClassId = dObjId;
  2431. if (GetSchemaCache()->IsDerivedClass(dObjectId, dClassId))
  2432. GetObjectCache()->DeleteObject(dObjId);
  2433. hTemp = GetObjectCache()->FindNext(dObjId, dObjId, dClassId);
  2434. }
  2435. }
  2436. }
  2437. }
  2438. }
  2439. }
  2440. }
  2441. }
  2442. }
  2443. if (SUCCEEDED(hr) && (dwFlags & WBEM_FLAG_REMOVE_CHILD_SECURITY))
  2444. {
  2445. // Is this a recursive put (WBEM_FLAG_REMOVE_CHILD_SECURITY)? We need to recursively erase all security on all child objects.
  2446. // * Enumerate all dependent objects that have SDs.
  2447. // * Call PutObject on each *with* the Use_SD flag, but without the remove_child_security
  2448. // flag
  2449. SQLIDs ObjIds, ClassIds, ScopeIds;
  2450. hr = CSQLExecProcedure::EnumerateSecuredChildren(pConn, &((CWmiDbController *)m_pController)->SchemaCache,
  2451. dObjectId, dClassId, dScopeID, ObjIds, ClassIds, ScopeIds);
  2452. if (SUCCEEDED(hr))
  2453. {
  2454. for (int i = 0; i < ObjIds.size(); i++)
  2455. {
  2456. // Get the old object.
  2457. // Strip off the __SECURITY_DESCRIPTOR property
  2458. // Put it again.
  2459. SQL_ID dObjectId = ObjIds.at(i),
  2460. dClassId = ClassIds.at(i),
  2461. dScopeId = ScopeIds.at(i);
  2462. _bstr_t sScopeKey;
  2463. hr = GetSchemaCache()->GetNamespaceName(dScopeId, NULL, &sScopeKey);
  2464. DWORD dwTemp;
  2465. IWbemClassObject *pObj = NULL;
  2466. hr = GetObjectData(pConn, dObjectId, dClassId, dScopeId,
  2467. 0, dwTemp, &pObj, FALSE, NULL);
  2468. CReleaseMe r (pObj);
  2469. if (SUCCEEDED(hr))
  2470. {
  2471. hr = pObj->Put(L"__SECURITY_DESCRIPTOR", 0, NULL, CIM_FLAG_ARRAY|CIM_UINT8);
  2472. if (SUCCEEDED(hr))
  2473. {
  2474. _bstr_t sPath;
  2475. hr = PutObject(pConn, NULL, dScopeId, sScopeKey, pObj,
  2476. WBEM_FLAG_USE_SECURITY_DESCRIPTOR, 0, sPath,
  2477. NULL, FALSE);
  2478. }
  2479. }
  2480. }
  2481. }
  2482. else if (hr == E_NOTIMPL)
  2483. hr = WBEM_S_NO_ERROR;
  2484. }
  2485. Exit:
  2486. return hr;
  2487. }
  2488. //***************************************************************************
  2489. //
  2490. // CWmiDbSession::UpdateHierarchy
  2491. //
  2492. //***************************************************************************
  2493. HRESULT CWmiDbSession::UpdateHierarchy(CSQLConnection *pConn, SQL_ID dClassId, DWORD dwFlags, LPCWSTR lpScopePath,
  2494. CWbemClassObjectProps *pProps, _IWmiObject *pObj)
  2495. {
  2496. HRESULT hr = WBEM_S_NO_ERROR;
  2497. // Enumerate subclasses (from the cache),
  2498. // forcibly update them, and add to ESS cache
  2499. int iNumDerived = 0;
  2500. SQL_ID *pIDs = NULL;
  2501. hr = GetSchemaCache()->GetDerivedClassList(dClassId, &pIDs, iNumDerived, TRUE);
  2502. if (SUCCEEDED(hr))
  2503. {
  2504. CDeleteMe <SQL_ID> d3 (pIDs);
  2505. // If there are instances, fail now.
  2506. BOOL bInstances = FALSE;
  2507. hr = CSQLExecProcedure::HasInstances(pConn, dClassId, pIDs, iNumDerived, bInstances);
  2508. if (bInstances)
  2509. return WBEM_E_CLASS_HAS_INSTANCES;
  2510. for (int i = 0; i < iNumDerived; i++)
  2511. {
  2512. IWbemClassObject *pSubClass = NULL;
  2513. hr = GetClassObject(pConn, pIDs[i], &pSubClass);
  2514. CReleaseMe r2 (pSubClass);
  2515. if (SUCCEEDED(hr))
  2516. {
  2517. _IWmiObject *pNew = NULL;
  2518. hr = ((_IWmiObject *)pObj)->Update(((_IWmiObject *)pSubClass), WBEM_FLAG_UPDATE_FORCE_MODE, &pNew);
  2519. if (SUCCEEDED(hr))
  2520. {
  2521. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  2522. {
  2523. ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID,
  2524. (LPWSTR)lpScopePath, pProps->lpClassName, pProps->dwGenus, pSubClass, pNew);
  2525. }
  2526. hr = UpdateHierarchy(pConn, pIDs[i], dwFlags, lpScopePath, pProps, pNew);
  2527. if (FAILED(hr))
  2528. break;
  2529. // Update the subclass object in the repository.
  2530. // Can only be done after all children have been updated.
  2531. hr = CSQLExecProcedure::UpdateClassBlob(pConn, pIDs[i], pNew);
  2532. if (FAILED(hr))
  2533. break;
  2534. }
  2535. else
  2536. break;
  2537. }
  2538. }
  2539. }
  2540. return hr;
  2541. }
  2542. //***************************************************************************
  2543. //
  2544. // CWmiDbSession::PutClass
  2545. //
  2546. //***************************************************************************
  2547. HRESULT CWmiDbSession::PutClass(
  2548. CSQLConnection *pConn,
  2549. /* [in] */ SQL_ID dScopeID,
  2550. /* [in] */ LPCWSTR lpScopePath,
  2551. CWbemClassObjectProps *pProps,
  2552. /* [in] */ IWbemClassObject *pObj,
  2553. DWORD dwFlags,
  2554. /* [in/out] */ SQL_ID &dObjectId,
  2555. /* [out] */ _bstr_t &sObjectPath,
  2556. bool &bChg,
  2557. BOOL bIgnoreDefaults)
  2558. {
  2559. HRESULT hr = WBEM_S_NO_ERROR;
  2560. SQL_ID dTempScopeID = 0;
  2561. bool bNewObj = (dObjectId == 0) ? 1 : 0;
  2562. SQL_ID dSuperClassId = 1;
  2563. SQL_ID dDynasty = 0;
  2564. wchar_t wSuperClass[450];
  2565. if (!m_pController ||
  2566. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  2567. return WBEM_E_SHUTTING_DOWN;
  2568. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  2569. return WBEM_E_INVALID_PARAMETER;
  2570. // See if anything changed.
  2571. if (dObjectId)
  2572. {
  2573. IWbemClassObject *pOldObj = NULL;
  2574. DWORD dwTemp;
  2575. hr = GetObjectData(pConn, dObjectId, 1, dScopeID,
  2576. 0, dwTemp, &pOldObj, FALSE, NULL);
  2577. CReleaseMe r (pOldObj);
  2578. if (SUCCEEDED(hr) && !(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  2579. {
  2580. DWORD dwRequired = 0;
  2581. if (pProps->lpClassName[0] == L'_')
  2582. dwRequired = WBEM_FULL_WRITE_REP;
  2583. else
  2584. dwRequired = WBEM_PARTIAL_WRITE_REP;
  2585. hr = VerifyObjectSecurity(pConn, dObjectId, 1, dScopeID, 0, dwRequired);
  2586. if (FAILED(hr))
  2587. {
  2588. return hr;
  2589. }
  2590. }
  2591. if (SUCCEEDED(hr))
  2592. {
  2593. // Backward compatibility: always log an event,
  2594. // even though nothing has changed.
  2595. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  2596. {
  2597. ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID,
  2598. (LPWSTR)lpScopePath, pProps->lpClassName, pProps->dwGenus, pOldObj, pObj);
  2599. }
  2600. hr = pOldObj->CompareTo(0, pObj);
  2601. if (WBEM_S_NO_ERROR == hr)
  2602. return WBEM_S_NO_ERROR; // Nothing changed. Don't bother updating.
  2603. else
  2604. {
  2605. // Did this impact subclasses? If so,
  2606. // enumerate and add ESS records.
  2607. BOOL bImmediate = FALSE;
  2608. hr = ((_IWmiObject *)pOldObj)->ReconcileWith(WMIOBJECT_RECONCILE_FLAG_TESTRECONCILE, (_IWmiObject *)pObj);
  2609. if (hr != WBEM_S_NO_ERROR)
  2610. {
  2611. hr = UpdateHierarchy(pConn, dObjectId, dwFlags, lpScopePath, pProps, (_IWmiObject *)pObj);
  2612. }
  2613. }
  2614. }
  2615. else
  2616. hr = WBEM_S_NO_ERROR;
  2617. }
  2618. else
  2619. {
  2620. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  2621. {
  2622. ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID,
  2623. (LPWSTR)lpScopePath, pProps->lpClassName, pProps->dwGenus, NULL, pObj);
  2624. }
  2625. }
  2626. bChg = true;
  2627. // Generate the object path.
  2628. if (!wcslen(pProps->lpRelPath) || !wcslen(pProps->lpClassName))
  2629. return WBEM_E_INVALID_OBJECT;
  2630. if (pProps->lpSuperClass && wcslen(pProps->lpSuperClass))
  2631. {
  2632. if (FAILED(GetSchemaCache()->GetClassID (pProps->lpSuperClass, dScopeID, dSuperClassId)))
  2633. return WBEM_E_INVALID_CLASS;
  2634. if (lpScopePath != NULL && wcslen(lpScopePath))
  2635. swprintf(wSuperClass, L"%s:%s", lpScopePath, pProps->lpSuperClass);
  2636. else
  2637. wcscpy(wSuperClass, pProps->lpSuperClass);
  2638. }
  2639. else
  2640. wSuperClass[0] = L'\0';
  2641. (GetSchemaCache()->GetClassID (pProps->lpDynasty, dScopeID, dDynasty));
  2642. if (SUCCEEDED(hr))
  2643. {
  2644. IRowset *pIRowset = NULL;
  2645. DWORD dwRows = 0;
  2646. DWORD dwClassFlags = 0;
  2647. IWbemQualifierSet *pQS = NULL;
  2648. hr = pObj->GetQualifierSet(&pQS);
  2649. if (SUCCEEDED(hr))
  2650. {
  2651. CReleaseMe r (pQS);
  2652. dwClassFlags = GetQualifierFlag(L"Abstract", pQS) ? REPDRVR_FLAG_ABSTRACT : 0;
  2653. dwClassFlags |= GetQualifierFlag(L"Singleton", pQS) ? REPDRVR_FLAG_SINGLETON : 0;
  2654. dwClassFlags |= GetQualifierFlag(L"Unkeyed", pQS) ? REPDRVR_FLAG_UNKEYED : 0;
  2655. dwClassFlags |= GetQualifierFlag(L"HasClassRefs", pQS) ? REPDRVR_FLAG_CLASSREFS : 0;
  2656. BOOL bExists = FALSE;
  2657. // If exists, only update the class if super class or flags changed
  2658. // (They can't change the name or scope without changing the
  2659. // path, right?)
  2660. _bstr_t sName;
  2661. SQL_ID dSuperClass = 1;
  2662. if (SUCCEEDED(GetSchemaCache()->GetClassInfo
  2663. (dObjectId, sName, dSuperClass, dTempScopeID, dwFlags)))
  2664. bExists = TRUE;
  2665. LPWSTR lpObjKey, lpParentKey;
  2666. lpObjKey = pProps->lpKeyString;
  2667. lpParentKey = GetKeyString(wSuperClass);
  2668. CDeleteMe <wchar_t> r2(lpParentKey);
  2669. if (!lpObjKey || !wcslen(lpObjKey))
  2670. {
  2671. ERRORTRACE((LOG_WBEMCORE, "Invalid object path in CWmiDbSession::PutClass (%S) \n", sObjectPath));
  2672. hr = WBEM_E_INVALID_PARAMETER;
  2673. }
  2674. else
  2675. {
  2676. // Insert the data.
  2677. // Ensure that we don't end up reporting to ourself.
  2678. // Enumerate the __Derivation property of the IWbemClassObject,
  2679. // and see if the class is in its own ancestry.
  2680. if (IsDerivedFrom(pObj, pProps->lpClassName, TRUE))
  2681. hr = WBEM_E_CIRCULAR_REFERENCE;
  2682. if (SUCCEEDED(hr))
  2683. {
  2684. _IWmiObject *pInt = NULL;
  2685. hr = pObj->QueryInterface(IID__IWmiObject, (void **)&pInt);
  2686. CReleaseMe r (pInt);
  2687. if (SUCCEEDED(hr))
  2688. {
  2689. BYTE *pBuff;
  2690. BYTE buff[128];
  2691. DWORD dwLen = 0;
  2692. pInt->Unmerge(0, 128, &dwLen, &buff);
  2693. if (dwLen > 0)
  2694. {
  2695. pBuff = new BYTE [dwLen];
  2696. if (pBuff)
  2697. {
  2698. DWORD dwLen1;
  2699. hr = pInt->Unmerge(0, dwLen, &dwLen1, pBuff);
  2700. if (SUCCEEDED(hr))
  2701. {
  2702. hr = CSQLExecProcedure::InsertClass(pConn, pProps->lpClassName, lpObjKey, sObjectPath, dScopeID,
  2703. dSuperClassId, dDynasty, 0, pBuff, dwLen1, dwClassFlags, dwFlags, dObjectId);
  2704. if (SUCCEEDED(hr))
  2705. {
  2706. if (!dDynasty)
  2707. dDynasty = dObjectId;
  2708. hr = GetSchemaCache()->AddClassInfo(dObjectId, pProps->lpClassName,
  2709. dSuperClassId, dDynasty, dScopeID, lpObjKey, dwClassFlags);
  2710. }
  2711. }
  2712. delete pBuff;
  2713. }
  2714. else
  2715. hr = WBEM_E_OUT_OF_MEMORY;
  2716. }
  2717. }
  2718. }
  2719. }
  2720. if (SUCCEEDED(hr))
  2721. {
  2722. // Get a map of this classes' property IDs
  2723. // Qualifiers won't be present, but that's OK now.
  2724. // ==============================================
  2725. Properties props;
  2726. if (!bNewObj)
  2727. hr = GetSchemaCache()->GetPropertyList(dObjectId, props);
  2728. // Iterate through all properties, qualifiers, methods.
  2729. // Only update ones that changed and update cache.
  2730. // Check off/Add ID as we encounter them.
  2731. // ====================================================
  2732. BSTR strName;
  2733. VARIANT vTemp;
  2734. CIMTYPE cimtype;
  2735. long lPropFlavor = 0;
  2736. IWbemQualifierSet *pQS = NULL;
  2737. // Properties
  2738. //((_IWmiObject *)pObj)->BeginEnumerationEx(WBEM_FLAG_CLASS_LOCAL_AND_OVERRIDES, WMIOBJECT_BEGINENUMEX_FLAG_GETEXTPROPS);
  2739. pObj->BeginEnumeration(WBEM_FLAG_CLASS_LOCAL_AND_OVERRIDES);
  2740. while (pObj->Next(0, &strName, &vTemp, &cimtype, &lPropFlavor) == S_OK)
  2741. {
  2742. CFreeMe f1 (strName);
  2743. pObj->GetPropertyQualifierSet(strName, &pQS);
  2744. if (pQS)
  2745. {
  2746. CReleaseMe r (pQS);
  2747. lPropFlavor = (REPDRVR_FLAG_CLASSREFS & dwClassFlags);
  2748. lPropFlavor |= (GetQualifierFlag(L"key", pQS)) ? REPDRVR_FLAG_KEY : 0;
  2749. lPropFlavor |= (GetQualifierFlag(L"indexed", pQS)) ? REPDRVR_FLAG_INDEXED : 0;
  2750. lPropFlavor |= (GetQualifierFlag(L"keyhole", pQS)) ? REPDRVR_FLAG_KEYHOLE : 0;
  2751. lPropFlavor |= (GetQualifierFlag(L"not_null", pQS)) ? REPDRVR_FLAG_NOT_NULL : 0;
  2752. }
  2753. if (bIgnoreDefaults)
  2754. VariantClear(&vTemp);
  2755. hr = InsertPropertyDef(pConn, pObj, dScopeID, dObjectId, strName, vTemp, cimtype, lPropFlavor, 0,props);
  2756. VariantClear(&vTemp);
  2757. if (FAILED(hr))
  2758. break;
  2759. }
  2760. // No need to insert qualifiers or methods.
  2761. // We are only creating schema so it can
  2762. // be queried when we get instances.
  2763. // Delete any properties, methods that
  2764. // were not found, remove from cache.
  2765. // Qualifiers can simply be deleted,
  2766. // since they aren't cached.
  2767. // ===================================
  2768. if (SUCCEEDED(hr) && !bNewObj)
  2769. {
  2770. _bstr_t sSQL;
  2771. bool bInit = false;
  2772. Properties::iterator item = props.begin();
  2773. while (item != props.end())
  2774. {
  2775. DWORD dwID = (*item).first;
  2776. if (!GetSchemaCache()->IsQualifier(dwID))
  2777. {
  2778. if (!(*item).second)
  2779. {
  2780. SQL_ID dClass = 0;
  2781. hr = GetSchemaCache()->GetPropertyInfo
  2782. (dwID, NULL, &dClass);
  2783. if (dClass == dObjectId)
  2784. {
  2785. CSQLExecProcedure::DeleteProperty(pConn, dwID);
  2786. GetSchemaCache()->DeleteProperty(dwID, dClass);
  2787. }
  2788. hr = WBEM_S_NO_ERROR;
  2789. }
  2790. }
  2791. item++;
  2792. }
  2793. }
  2794. else if (FAILED(hr) && bNewObj)
  2795. {
  2796. hr = GetSchemaCache()->DeleteClass(dObjectId);
  2797. }
  2798. }
  2799. }
  2800. }
  2801. return hr;
  2802. }
  2803. //***************************************************************************
  2804. //
  2805. // CWmiDbSession::InsertPropertyDef
  2806. //
  2807. //***************************************************************************
  2808. HRESULT CWmiDbSession::InsertPropertyDef(CSQLConnection *pConn,
  2809. IWbemClassObject *pObj, SQL_ID dScopeId,
  2810. SQL_ID dObjectId, LPWSTR lpPropName, VARIANT vDefault,
  2811. CIMTYPE cimtype, long dwFlags, DWORD dRefId,
  2812. Properties &props)
  2813. {
  2814. HRESULT hr = WBEM_S_NO_ERROR;
  2815. bool bArray = false;
  2816. if (cimtype & CIM_FLAG_ARRAY)
  2817. bArray = true;
  2818. dwFlags |= (bArray) ? REPDRVR_FLAG_ARRAY : 0;
  2819. cimtype &= ~CIM_FLAG_ARRAY;
  2820. // If this is an embedded object or reference,
  2821. // set the class ID of the embedded object, if any.
  2822. SQL_ID dRefClassId = 0;
  2823. if (cimtype == CIM_REFERENCE || cimtype == CIM_OBJECT)
  2824. {
  2825. IWbemQualifierSet *pQS = NULL;
  2826. hr = pObj->GetPropertyQualifierSet(lpPropName, &pQS);
  2827. if (SUCCEEDED(hr))
  2828. {
  2829. VARIANT vValue;
  2830. VariantInit(&vValue);
  2831. CReleaseMe r (pQS);
  2832. CClearMe c (&vValue);
  2833. hr = pQS->Get(L"CIMTYPE", 0, &vValue, NULL);
  2834. // Since previously, wbem did not do any type checking of references
  2835. // or embedded objects, we generate the IDs for the classes if
  2836. // they aren't already present. This will still fail for instances.
  2837. if (!_wcsnicmp(vValue.bstrVal, L"ref", 3) &&
  2838. wcslen(vValue.bstrVal) > 3)
  2839. {
  2840. LPWSTR lpPtr = (LPWSTR)vValue.bstrVal;
  2841. lpPtr += 4;
  2842. hr = GetSchemaCache()->GetClassID(lpPtr, dScopeId, dRefClassId);
  2843. if (hr == WBEM_E_NOT_FOUND)
  2844. {
  2845. _bstr_t sScopeKey;
  2846. hr = GetSchemaCache()->GetNamespaceName(dScopeId, NULL, &sScopeKey);
  2847. if (SUCCEEDED(hr))
  2848. {
  2849. _bstr_t sNewName = lpPtr;
  2850. sNewName += L"?";
  2851. sNewName += sScopeKey;
  2852. dRefClassId = CRC64::GenerateHashValue(sNewName);
  2853. hr = WBEM_S_NO_ERROR;
  2854. }
  2855. }
  2856. }
  2857. else if (!_wcsnicmp(vValue.bstrVal, L"object", 6) &&
  2858. wcslen(vValue.bstrVal) > 6)
  2859. {
  2860. LPWSTR lpPtr = (LPWSTR)vValue.bstrVal;
  2861. lpPtr += 7;
  2862. hr = GetSchemaCache()->GetClassID(lpPtr, dScopeId, dRefClassId);
  2863. if (hr == WBEM_E_NOT_FOUND)
  2864. {
  2865. _bstr_t sScopeKey;
  2866. hr = GetSchemaCache()->GetNamespaceName(dScopeId, NULL, &sScopeKey);
  2867. if (SUCCEEDED(hr))
  2868. {
  2869. _bstr_t sNewName = lpPtr;
  2870. sNewName += L"?";
  2871. sNewName += sScopeKey;
  2872. dRefClassId = CRC64::GenerateHashValue(sNewName);
  2873. hr = WBEM_S_NO_ERROR;
  2874. }
  2875. }
  2876. }
  2877. }
  2878. }
  2879. // We can't verify that a property changed, since we currently aren't
  2880. // caching the defaults, so will insert regardless.
  2881. DWORD dwPropertyID = 0;
  2882. if (wcslen(lpPropName) > REPDRVR_NAME_LIMIT)
  2883. {
  2884. hr = WBEM_E_PROPERTY_NAME_TOO_WIDE;
  2885. }
  2886. else
  2887. {
  2888. BOOL bChg = TRUE;
  2889. SQL_ID dOrigClass = 0;
  2890. if ((GetSchemaCache()->GetPropertyID
  2891. (lpPropName, dObjectId, dwFlags, cimtype, dwPropertyID, &dOrigClass)) == WBEM_S_NO_ERROR)
  2892. {
  2893. }
  2894. else if (!(dwFlags & (REPDRVR_FLAG_NONPROP &~ REPDRVR_FLAG_METHOD)))
  2895. {
  2896. // Does this property exist on the derived class already?
  2897. if (SUCCEEDED(hr))
  2898. {
  2899. hr = GetSchemaCache()->FindProperty(dObjectId, lpPropName, dwFlags, cimtype);
  2900. }
  2901. }
  2902. if (SUCCEEDED(hr))
  2903. {
  2904. BOOL bIsKey = FALSE;
  2905. if (bChg)
  2906. {
  2907. LPWSTR lpVal = GetStr(vDefault);
  2908. CDeleteMe <wchar_t> r(lpVal);
  2909. hr = CSQLExecProcedure::InsertClassData(pConn, pObj, &((CWmiDbController *)m_pController)->SchemaCache,
  2910. dScopeId, dObjectId, lpPropName, cimtype, GetStorageType(cimtype, bArray), lpVal,
  2911. dRefClassId, dRefId, dwFlags, 0, 0, dwPropertyID, dOrigClass, &bIsKey);
  2912. }
  2913. if (SUCCEEDED(hr))
  2914. {
  2915. hr = GetSchemaCache()->AddPropertyInfo (dwPropertyID,
  2916. lpPropName, dObjectId, GetStorageType(cimtype, bArray), cimtype, dwFlags,
  2917. 0, L"", dRefId, 0); // don't cache the default!
  2918. if (bIsKey)
  2919. GetSchemaCache()->SetIsKey(dObjectId, dwPropertyID);
  2920. props[dwPropertyID] = 1;
  2921. }
  2922. }
  2923. }
  2924. return hr;
  2925. }
  2926. //***************************************************************************
  2927. //
  2928. // CWmiDbSession::InsertQualifiers
  2929. //
  2930. //***************************************************************************
  2931. HRESULT CWmiDbSession::InsertQualifiers (CSQLConnection *pConn, IWmiDbHandle *pScope, SQL_ID dObjectId,
  2932. DWORD PropID, DWORD Flags, IWbemQualifierSet *pQS,
  2933. Properties &props)
  2934. {
  2935. HRESULT hr = WBEM_S_NO_ERROR;
  2936. BSTR strName;
  2937. VARIANT vTemp;
  2938. VariantInit(&vTemp);
  2939. long lPropFlavor = 0;
  2940. pQS->BeginEnumeration(0);
  2941. while (pQS->Next(0, &strName, &vTemp, &lPropFlavor) == S_OK)
  2942. {
  2943. CFreeMe f (strName);
  2944. lPropFlavor = lPropFlavor&~WBEM_FLAVOR_ORIGIN_PROPAGATED&~WBEM_FLAVOR_ORIGIN_SYSTEM&~WBEM_FLAVOR_AMENDED;
  2945. hr = InsertQualifier(pConn, pScope, dObjectId, strName, vTemp,
  2946. lPropFlavor, Flags & REPDRVR_FLAG_QUALIFIER, PropID, props);
  2947. VariantClear(&vTemp);
  2948. if (FAILED(hr))
  2949. break;
  2950. }
  2951. pQS->EndEnumeration();
  2952. return hr;
  2953. }
  2954. //***************************************************************************
  2955. //
  2956. // CWmiDbSession::InsertQualifier
  2957. //
  2958. //***************************************************************************
  2959. HRESULT CWmiDbSession::InsertQualifier( CSQLConnection *pConn,IWmiDbHandle *pScope,
  2960. SQL_ID dObjectId,
  2961. LPWSTR lpQualifierName, VARIANT vValue,
  2962. long lQfrFlags, DWORD dwFlags, DWORD PropID,
  2963. Properties &props)
  2964. {
  2965. HRESULT hr = WBEM_S_NO_ERROR;
  2966. dwFlags |= REPDRVR_FLAG_QUALIFIER;
  2967. // This will only insert the qualifier definition
  2968. // and the initial data.
  2969. // Insert the qualifier, unless its one of the
  2970. // system quartet: key, indexed, keyhole, not_null
  2971. // ==================================================
  2972. if (!_wcsicmp(lpQualifierName, L"abstract"))
  2973. return WBEM_S_NO_ERROR;
  2974. if (!_wcsicmp(lpQualifierName, L"cimtype"))
  2975. {
  2976. if ((wcslen(vValue.bstrVal) > 3 && !_wcsnicmp(vValue.bstrVal, L"ref", 3)) ||
  2977. (wcslen(vValue.bstrVal) > 6 && !_wcsnicmp(vValue.bstrVal, L"object", 6)))
  2978. {
  2979. }
  2980. else
  2981. return WBEM_S_NO_ERROR; // CIMTypes are generated automatically.
  2982. }
  2983. bool bArray = false;
  2984. CIMTYPE ct;
  2985. switch((vValue.vt &~ CIM_FLAG_ARRAY))
  2986. {
  2987. case VT_R4:
  2988. case VT_R8:
  2989. ct = CIM_REAL64;
  2990. break;
  2991. case VT_BSTR:
  2992. ct = CIM_STRING;
  2993. break;
  2994. case VT_BOOL:
  2995. ct = CIM_BOOLEAN;
  2996. break;
  2997. default:
  2998. ct = CIM_UINT32;
  2999. break;
  3000. }
  3001. if (vValue.vt & VT_ARRAY)
  3002. bArray = true;
  3003. dwFlags |= (bArray) ? REPDRVR_FLAG_ARRAY : 0;
  3004. DWORD dwPropertyID = 0;
  3005. if (wcslen(lpQualifierName) > REPDRVR_NAME_LIMIT)
  3006. {
  3007. hr = WBEM_E_QUALIFIER_NAME_TOO_WIDE;
  3008. }
  3009. else
  3010. {
  3011. if (SUCCEEDED(hr))
  3012. {
  3013. LPWSTR lpVal = GetStr(vValue);
  3014. CDeleteMe <wchar_t> r(lpVal);
  3015. try
  3016. {
  3017. GetSchemaCache()->GetPropertyID (lpQualifierName, 1, dwFlags, ct, dwPropertyID);
  3018. hr = CSQLExecProcedure::InsertClassData(pConn, NULL, &((CWmiDbController *)m_pController)->SchemaCache, 0, 1, lpQualifierName,
  3019. ct, GetStorageType(ct, bArray), lpVal,0, PropID, dwFlags, lQfrFlags, 0, dwPropertyID);
  3020. if (SUCCEEDED(hr))
  3021. {
  3022. hr = GetSchemaCache()->AddPropertyInfo (dwPropertyID,
  3023. lpQualifierName, 1, GetStorageType(ct, bArray), ct, dwFlags,
  3024. 0, L"", PropID, lQfrFlags); // don't cache the default!
  3025. // Add any array defaults.
  3026. // =======================
  3027. if (vValue.vt & VT_ARRAY)
  3028. hr = InsertArray(pConn, pScope, dObjectId, 1, dwPropertyID, vValue, lQfrFlags, PropID);
  3029. }
  3030. }
  3031. catch (...)
  3032. {
  3033. hr = WBEM_E_CRITICAL_ERROR;
  3034. }
  3035. }
  3036. }
  3037. return hr;
  3038. }
  3039. //***************************************************************************
  3040. //
  3041. // CWmiDbSession::PutInstance
  3042. //
  3043. //***************************************************************************
  3044. HRESULT CWmiDbSession::PutInstance(
  3045. CSQLConnection *pConn,
  3046. IWmiDbHandle *pScope,
  3047. /* [in] */ SQL_ID dScopeID,
  3048. /* [in] */ LPCWSTR lpScopePath,
  3049. CWbemClassObjectProps *pProps,
  3050. /* [in] */ IWbemClassObject *pObj,
  3051. DWORD dwFlags,
  3052. /* [in/out] */ SQL_ID &dObjectId,
  3053. /* [out] */ SQL_ID &dClassId,
  3054. /* [out] */ _bstr_t &sObjectPath,
  3055. bool &bChg)
  3056. {
  3057. HRESULT hr = WBEM_S_NO_ERROR;
  3058. bool bUpdate = (dObjectId == 0) ? false : true;
  3059. if (!m_pController ||
  3060. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  3061. return WBEM_E_SHUTTING_DOWN;
  3062. SQL_ID dTestId = dObjectId;
  3063. if (!dTestId)
  3064. {
  3065. if (pProps->lpKeyString)
  3066. dTestId = CRC64::GenerateHashValue(pProps->lpKeyString);
  3067. }
  3068. BOOL bGetSD = FALSE;
  3069. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  3070. bGetSD = TRUE;
  3071. IWbemClassObject *pOldObj = NULL;
  3072. DWORD dwTemp;
  3073. hr = GetObjectData(pConn, dTestId, dClassId, dScopeID,
  3074. 0, dwTemp, &pOldObj, FALSE, NULL, bGetSD);
  3075. CReleaseMe r (pOldObj);
  3076. if (SUCCEEDED(hr))
  3077. {
  3078. if (SUCCEEDED(hr) && !(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  3079. {
  3080. DWORD dwRequired = 0;
  3081. if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  3082. dwRequired = WRITE_DAC;
  3083. else
  3084. {
  3085. if (pProps->lpClassName[0] == L'_')
  3086. dwRequired = WBEM_FULL_WRITE_REP;
  3087. else
  3088. dwRequired = WBEM_PARTIAL_WRITE_REP;
  3089. }
  3090. hr = VerifyObjectSecurity(pConn, dTestId, dClassId, dScopeID, 0, dwRequired);
  3091. if (FAILED(hr))
  3092. {
  3093. return hr;
  3094. }
  3095. }
  3096. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  3097. {
  3098. LPWSTR lpClass = pProps->lpClassName;
  3099. BOOL bRelease = FALSE;
  3100. if (IsDerivedFrom(pObj, L"__Namespace"))
  3101. {
  3102. lpClass = GetPropertyVal(L"Name", pObj);
  3103. bRelease = TRUE;
  3104. }
  3105. ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID,
  3106. (LPWSTR)lpScopePath, lpClass, pProps->dwGenus, pOldObj, pObj);
  3107. if (bRelease)
  3108. delete lpClass;
  3109. }
  3110. hr = pOldObj->CompareTo(0, pObj);
  3111. if (WBEM_S_NO_ERROR == hr)
  3112. return WBEM_S_NO_ERROR; // Nothing changed. Don't bother updating.
  3113. }
  3114. else
  3115. {
  3116. hr = WBEM_S_NO_ERROR;
  3117. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  3118. {
  3119. ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID,
  3120. (LPWSTR)lpScopePath, pProps->lpClassName, pProps->dwGenus, NULL, pObj);
  3121. }
  3122. }
  3123. bChg = true;
  3124. if (SUCCEEDED(hr))
  3125. {
  3126. IRowset *pIRowset = NULL;
  3127. DWORD dwNumRows = 0;
  3128. // Generate unkeyed or keyhole path if none (and if class is one of the two)
  3129. if (!bUpdate )
  3130. {
  3131. bool bUnkeyed = false;
  3132. _bstr_t sName;
  3133. SQL_ID dTemp1, dTemp2;
  3134. DWORD dwFlags = 0;
  3135. hr = GetSchemaCache()->GetClassInfo (dClassId, sName, dTemp1, dTemp2, dwFlags);
  3136. if (SUCCEEDED(hr) && (dwFlags & REPDRVR_FLAG_UNKEYED))
  3137. {
  3138. bUnkeyed = true;
  3139. hr = CSQLExecProcedure::GetNextUnkeyedPath(pConn, dClassId, sObjectPath);
  3140. }
  3141. // Cannot add instances to an abstract class.
  3142. if (dwFlags & REPDRVR_FLAG_ABSTRACT)
  3143. return WBEM_E_INVALID_OPERATION;
  3144. DWORD dwKeyholePropID = 0;
  3145. _bstr_t sKeyholeProp;
  3146. if (SUCCEEDED(hr) && SUCCEEDED(GetSchemaCache()->GetKeyholeProperty(dClassId, dwKeyholePropID, sKeyholeProp)))
  3147. {
  3148. hr = SetKeyhole(pConn, pObj, dwKeyholePropID, sKeyholeProp, lpScopePath, sObjectPath);
  3149. delete pProps->lpRelPath;
  3150. pProps->lpRelPath = GetPropertyVal(L"__RelPath", pObj);
  3151. }
  3152. if (!bUnkeyed && !pProps->lpRelPath)
  3153. hr = WBEM_E_INVALID_OBJECT; // path cannot be blank at this point.
  3154. }
  3155. if (SUCCEEDED(hr)) // we have a valid path.
  3156. hr = InsertPropertyValues(pConn, pScope, sObjectPath, dObjectId, dClassId, dScopeID, dwFlags, pProps, pObj);
  3157. }
  3158. return hr;
  3159. }
  3160. //***************************************************************************
  3161. //
  3162. // CWmiDbSession::SetKeyhole
  3163. //
  3164. //***************************************************************************
  3165. HRESULT CWmiDbSession::SetKeyhole (CSQLConnection *pConn, IWbemClassObject *pObj, DWORD dwKeyholePropID,
  3166. LPWSTR sKeyholeProp, LPCWSTR lpScopePath, _bstr_t &sPath)
  3167. {
  3168. HRESULT hr = WBEM_S_NO_ERROR;
  3169. // See if it is populated.
  3170. CIMTYPE ct = 0;
  3171. long lFlags = 0;
  3172. VARIANT vTemp;
  3173. VariantInit(&vTemp);
  3174. _bstr_t sNewValue;
  3175. SQL_ID dNextId = 0;
  3176. hr = pObj->Get(sKeyholeProp, 0, &vTemp, &ct, &lFlags);
  3177. LPWSTR lpVal = GetStr(vTemp);
  3178. CDeleteMe <wchar_t> r(lpVal);
  3179. VariantClear(&vTemp);
  3180. if (!lpVal || !wcslen(lpVal) || !_wcsicmp(lpVal,L"0"))
  3181. {
  3182. // Execute stored procedure.
  3183. // =========================
  3184. hr = CSQLExecProcedure::GetNextKeyhole(pConn, dwKeyholePropID, dNextId);
  3185. if (SUCCEEDED(hr))
  3186. {
  3187. // If a string property, just
  3188. // convert the number to text.
  3189. // ==========================
  3190. if (ct == CIM_STRING) // We really want a GUID here!!!!
  3191. {
  3192. wchar_t szTmp[20];
  3193. swprintf(szTmp, L"%ld", dNextId);
  3194. V_BSTR(&vTemp) = szTmp;
  3195. vTemp.vt = VT_BSTR;
  3196. }
  3197. else
  3198. {
  3199. V_I4(&vTemp) = dNextId;
  3200. vTemp.vt = VT_I4;
  3201. }
  3202. // Try to update the key value,
  3203. // and get the object path again.
  3204. // ==============================
  3205. hr = pObj->Put(sKeyholeProp, 0, &vTemp, ct);
  3206. if (SUCCEEDED(hr))
  3207. {
  3208. hr = pObj->Get(L"__RelPath", 0, &vTemp, NULL, NULL);
  3209. sPath = vTemp.bstrVal;
  3210. if (lpScopePath != NULL)
  3211. {
  3212. _bstr_t sTemp = sPath;
  3213. sPath = _bstr_t(lpScopePath) + L":" + sTemp;
  3214. }
  3215. }
  3216. }
  3217. }
  3218. return hr;
  3219. }
  3220. InsertQfrValues * ReAllocQfrValues (InsertQfrValues *pVals, int iNumVals, int iAdd)
  3221. {
  3222. InsertQfrValues * pRet = new InsertQfrValues[iNumVals + iAdd];
  3223. if (pRet)
  3224. {
  3225. int iSize = sizeof(InsertQfrValues) * iNumVals;
  3226. /*
  3227. for (int i = 0; i < iNumVals; i++)
  3228. {
  3229. if (pVals[i].pValue)
  3230. iSize += wcslen(pVals[i].pValue)+ 1;
  3231. if (pVals[i].pRefKey)
  3232. iSize += wcslen(pVals[i].pRefKey) + 1;
  3233. }
  3234. */
  3235. memcpy(pRet, pVals, iSize);
  3236. delete pVals;
  3237. }
  3238. else
  3239. delete pVals;
  3240. return pRet;
  3241. }
  3242. // Strip off local prefixes. Any unresolved path
  3243. // not in this format might not be an object stored
  3244. // in this database.
  3245. LPWSTR StripUnresolvedName (LPWSTR lpPath)
  3246. {
  3247. LPWSTR lpRet = new wchar_t [wcslen(lpPath) + 1];
  3248. if (lpRet)
  3249. {
  3250. if (wcslen(lpPath) > 2)
  3251. {
  3252. if (wcsstr(lpPath, L"\\\\.\\root"))
  3253. lpPath += 9;
  3254. }
  3255. wcscpy(lpRet, lpPath);
  3256. }
  3257. return lpRet;
  3258. }
  3259. //***************************************************************************
  3260. //
  3261. // TestSD
  3262. //
  3263. //***************************************************************************
  3264. HRESULT TestSD(VARIANT * pvTemp)
  3265. {
  3266. if(pvTemp->vt != (VT_ARRAY | VT_UI1))
  3267. {
  3268. return WBEM_E_INVALID_PARAMETER;
  3269. }
  3270. SAFEARRAY * psa = pvTemp->parray;
  3271. PSECURITY_DESCRIPTOR pSD;
  3272. HRESULT hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pSD);
  3273. if(FAILED(hr))
  3274. return WBEM_E_INVALID_PARAMETER;
  3275. BOOL bRet = IsValidSecurityDescriptor(pSD);
  3276. if(bRet == FALSE)
  3277. {
  3278. SafeArrayUnaccessData(psa);
  3279. return WBEM_E_INVALID_PARAMETER;
  3280. }
  3281. PSID pSid = 0;
  3282. BOOL bDefaulted;
  3283. BOOL bRes = GetSecurityDescriptorOwner(pSD, &pSid, &bDefaulted);
  3284. if (!bRes || !IsValidSid(pSid))
  3285. {
  3286. SafeArrayUnaccessData(psa);
  3287. return WBEM_E_INVALID_PARAMETER;
  3288. }
  3289. pSid = 0;
  3290. bRes = GetSecurityDescriptorGroup(pSD, &pSid, &bDefaulted);
  3291. if (!bRes || !IsValidSid(pSid))
  3292. {
  3293. SafeArrayUnaccessData(psa);
  3294. return WBEM_E_INVALID_PARAMETER;
  3295. }
  3296. SafeArrayUnaccessData(psa);
  3297. return (bRet) ? S_OK : WBEM_E_INVALID_PARAMETER;
  3298. }
  3299. //***************************************************************************
  3300. //
  3301. // CWmiDbSession::InsertPropertyValues
  3302. //
  3303. //***************************************************************************
  3304. HRESULT CWmiDbSession::InsertPropertyValues (CSQLConnection *pConn,
  3305. IWmiDbHandle *pScope,
  3306. LPWSTR lpPath,
  3307. SQL_ID &dObjectId,
  3308. SQL_ID dClassId,
  3309. SQL_ID dScopeId,
  3310. DWORD dwFlags,
  3311. CWbemClassObjectProps *pProps,
  3312. IWbemClassObject *pObj)
  3313. {
  3314. HRESULT hr = WBEM_S_NO_ERROR;
  3315. BSTR strName;
  3316. CIMTYPE cimtype;
  3317. long lPropFlavor = 0;
  3318. SQL_ID dRefClassId = 0, dRefID = 0;
  3319. CWStringArray arrObjProps;
  3320. int iPos = 0, iQfrPos = 0;
  3321. bool bDone = false;
  3322. VARIANT vTemp;
  3323. BOOL bRemoveSD = FALSE;
  3324. CClearMe c (&vTemp);
  3325. Properties props;
  3326. InsertPropValues *pPropValues = NULL;
  3327. InsertQfrValues *pQVals = NULL;
  3328. LPWSTR lpCount = GetPropertyVal(L"__Property_Count", pObj);
  3329. CDeleteMe <wchar_t> r(lpCount);
  3330. int iNumProps = 10;
  3331. if (lpCount)
  3332. iNumProps += _wtoi(lpCount);
  3333. if (iNumProps)
  3334. {
  3335. pPropValues = new InsertPropValues[iNumProps];
  3336. if (!pPropValues)
  3337. return WBEM_E_OUT_OF_MEMORY;
  3338. }
  3339. if (!m_pController ||
  3340. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  3341. {
  3342. delete pPropValues;
  3343. return WBEM_E_SHUTTING_DOWN;
  3344. }
  3345. // Insert properties.
  3346. // ==================
  3347. ((_IWmiObject *)pObj)->BeginEnumerationEx(WBEM_FLAG_NONSYSTEM_ONLY, WMIOBJECT_BEGINENUMEX_FLAG_GETEXTPROPS);
  3348. // ((_IWmiObject *)pObj)->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
  3349. while (pObj->Next(0, &strName, &vTemp, &cimtype, &lPropFlavor) == S_OK)
  3350. {
  3351. CFreeMe f (strName);
  3352. // Ignore security unless they are setting it explicitly.
  3353. if (!_wcsicmp(strName, L"__SECURITY_DESCRIPTOR"))
  3354. {
  3355. if (!(dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR))
  3356. {
  3357. VariantClear(&vTemp);
  3358. continue;
  3359. }
  3360. else
  3361. {
  3362. if (vTemp.vt == VT_NULL)
  3363. bRemoveSD = TRUE;
  3364. }
  3365. }
  3366. // Skip embedded objects and arrays
  3367. // until we have an ObjectId...
  3368. // ===================================
  3369. IWbemQualifierSet *pQS = NULL;
  3370. hr = pObj->GetPropertyQualifierSet(strName, &pQS);
  3371. if (SUCCEEDED(hr))
  3372. {
  3373. CReleaseMe r (pQS);
  3374. if ((GetQualifierFlag(L"not_null", pQS) != 0) && (vTemp.vt == VT_NULL))
  3375. {
  3376. hr = WBEM_E_ILLEGAL_NULL;
  3377. VariantClear(&vTemp);
  3378. break;
  3379. }
  3380. }
  3381. if ((cimtype == CIM_OBJECT && vTemp.vt == VT_UNKNOWN) || ((cimtype & CIM_FLAG_ARRAY) && (vTemp.vt & CIM_FLAG_ARRAY)))
  3382. arrObjProps.Add(strName);
  3383. else
  3384. {
  3385. DWORD dPropID, dwFlags2, dwType;
  3386. SQL_ID dNewClassID = dClassId;
  3387. hr = GetSchemaCache()->GetPropertyID(strName, dClassId, 0, cimtype,
  3388. dPropID, &dNewClassID, &dwFlags2, &dwType);
  3389. if (SUCCEEDED(hr))
  3390. {
  3391. LPWSTR lpVal = GetStr(vTemp);
  3392. CDeleteMe <wchar_t> r(lpVal);
  3393. pPropValues[iPos].iPropID = dPropID;
  3394. pPropValues[iPos].pValue = NULL;
  3395. pPropValues[iPos].pRefKey = NULL;
  3396. pPropValues[iPos].bLong = false;
  3397. pPropValues[iPos].iFlavor = 0;
  3398. pPropValues[iPos].iQfrID = 0;
  3399. pPropValues[iPos].dClassId = dNewClassID;
  3400. pPropValues[iPos].iStorageType = dwType;
  3401. pPropValues[iPos].bIndexed = (dwFlags2 & (REPDRVR_FLAG_INDEXED + REPDRVR_FLAG_KEY)) ? TRUE : FALSE;
  3402. if (cimtype == CIM_REFERENCE)
  3403. {
  3404. // If no scope, don't bother trying to
  3405. // store this reference,
  3406. // since the end result will be invalid.
  3407. // ======================================
  3408. if (!pScope)
  3409. {
  3410. VariantClear(&vTemp);
  3411. continue;
  3412. }
  3413. pPropValues[iPos].bIndexed = TRUE; // References are always keys
  3414. LPWSTR lpTemp = NULL;
  3415. IWbemPath *pPath = NULL;
  3416. hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER,
  3417. IID_IWbemPath, (LPVOID *) &pPath);
  3418. CReleaseMe r8 (pPath);
  3419. if (SUCCEEDED(hr))
  3420. {
  3421. if (lpVal)
  3422. {
  3423. pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, lpVal);
  3424. hr = NormalizeObjectPathGet(pScope, pPath, &lpTemp, NULL, NULL, NULL, pConn);
  3425. CDeleteMe <wchar_t> r1(lpTemp);
  3426. if (SUCCEEDED(hr))
  3427. {
  3428. LPWSTR lpTemp2 = NULL;
  3429. lpTemp2 = GetKeyString(lpTemp);
  3430. CDeleteMe <wchar_t> d (lpTemp2);
  3431. pPropValues[iPos].pRefKey = new wchar_t [21];
  3432. if (pPropValues[iPos].pRefKey)
  3433. swprintf(pPropValues[iPos].pRefKey, L"%I64d", CRC64::GenerateHashValue(lpTemp2));
  3434. else
  3435. hr = WBEM_E_OUT_OF_MEMORY;
  3436. }
  3437. else
  3438. {
  3439. hr = WBEM_S_NO_ERROR;
  3440. // Strip off the root namespace prefix and generate the
  3441. // pseudo-name. We have no way of knowing if they entered this
  3442. // path correctly.
  3443. LPWSTR lpTemp3 = StripUnresolvedName (lpVal);
  3444. CDeleteMe <wchar_t> d2 (lpTemp3);
  3445. LPWSTR lpTemp2 = NULL;
  3446. lpTemp2 = GetKeyString(lpTemp3);
  3447. CDeleteMe <wchar_t> d (lpTemp2);
  3448. pPropValues[iPos].pRefKey = new wchar_t [21];
  3449. if (pPropValues[iPos].pRefKey)
  3450. swprintf(pPropValues[iPos].pRefKey, L"%I64d", CRC64::GenerateHashValue(lpTemp2));
  3451. else
  3452. hr = WBEM_E_OUT_OF_MEMORY;
  3453. }
  3454. pPropValues[iPos].pValue = new wchar_t[wcslen(lpVal)+1];
  3455. if (pPropValues[iPos].pValue)
  3456. wcscpy(pPropValues[iPos].pValue,lpVal);
  3457. else
  3458. hr = WBEM_E_OUT_OF_MEMORY;
  3459. }
  3460. else
  3461. pPropValues[iPos].pValue = NULL;
  3462. }
  3463. else
  3464. {
  3465. VariantClear(&vTemp);
  3466. break;
  3467. }
  3468. }
  3469. else
  3470. {
  3471. if (lpVal)
  3472. {
  3473. pPropValues[iPos].pValue = new wchar_t[wcslen(lpVal)+1];
  3474. if (pPropValues[iPos].pValue)
  3475. wcscpy(pPropValues[iPos].pValue,lpVal);
  3476. else
  3477. hr = WBEM_E_OUT_OF_MEMORY;
  3478. }
  3479. else
  3480. pPropValues[iPos].pValue = NULL;
  3481. pPropValues[iPos].pRefKey = NULL;
  3482. }
  3483. pPropValues[iPos].iPos = 0;
  3484. iPos++;
  3485. }
  3486. else
  3487. {
  3488. VariantClear(&vTemp);
  3489. break;
  3490. }
  3491. }
  3492. VariantClear(&vTemp);
  3493. }
  3494. LPWSTR lpObjectKey = pProps->lpKeyString;
  3495. if (!wcslen(lpObjectKey))
  3496. {
  3497. ERRORTRACE((LOG_WBEMCORE, "Invalid object path in CWmiDbSession::InsertPropertyValues (%S) \n", lpPath));
  3498. delete pProps->lpKeyString;
  3499. lpObjectKey = new wchar_t [wcslen(lpPath)+1];
  3500. if (lpObjectKey)
  3501. wcscpy(lpObjectKey, lpPath);
  3502. else
  3503. hr = WBEM_E_OUT_OF_MEMORY;
  3504. pProps->lpKeyString = lpObjectKey;
  3505. }
  3506. if (SUCCEEDED(hr))
  3507. {
  3508. BOOL bCheck=FALSE;
  3509. CSQLExecProcedure::NeedsToCheckKeyMigration(bCheck);
  3510. if (bCheck)
  3511. {
  3512. SQL_ID *pIDs= NULL;
  3513. int iNumIDs = 0;
  3514. hr = GetSchemaCache()->GetHierarchy(dClassId, &pIDs, iNumIDs);
  3515. if (SUCCEEDED(hr))
  3516. {
  3517. hr = CSQLExecProcedure::CheckKeyMigration(pConn, lpObjectKey, pProps->lpClassName,
  3518. dClassId, dScopeId, pIDs, iNumIDs);
  3519. delete pIDs;
  3520. }
  3521. }
  3522. }
  3523. if (SUCCEEDED(hr))
  3524. hr = CSQLExecProcedure::InsertPropertyBatch (pConn, lpObjectKey, lpPath, pProps->lpClassName, dClassId,
  3525. dScopeId, dwFlags, pPropValues, iPos,
  3526. dObjectId);
  3527. delete pPropValues;
  3528. // If there's no scope, quit now.
  3529. // This can only happen if we are only updating
  3530. // the security descriptor.
  3531. // ============================================
  3532. if (!pScope)
  3533. return hr;
  3534. // Insert qualifiers next.
  3535. // ======================
  3536. if (SUCCEEDED(hr))
  3537. {
  3538. iQfrPos = 0;
  3539. iNumProps *=2 + 10 + arrObjProps.Size(); // How do we calculate how many qualifiers there will be??
  3540. pQVals = new InsertQfrValues[iNumProps];
  3541. if (!pQVals)
  3542. return WBEM_E_OUT_OF_MEMORY;
  3543. VariantClear(&vTemp);
  3544. // PROPERTY QUALIFIERS
  3545. pObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
  3546. while (pObj->Next(0, &strName, &vTemp, &cimtype, &lPropFlavor) == S_OK)
  3547. {
  3548. CFreeMe f (strName);
  3549. IWbemQualifierSet *pQS = NULL;
  3550. hr = pObj->GetPropertyQualifierSet(strName, &pQS);
  3551. if (hr == WBEM_S_NO_ERROR)
  3552. {
  3553. CReleaseMe r (pQS);
  3554. DWORD dwRefID = 0;
  3555. hr = GetSchemaCache()->GetPropertyID(strName, dClassId, 0, cimtype, dwRefID);
  3556. if (SUCCEEDED(hr))
  3557. hr = FormatBatchInsQfrs(pConn, pScope, dObjectId, dClassId, dwRefID, pQS, iQfrPos, &pQVals, props, iNumProps);
  3558. }
  3559. VariantClear(&vTemp);
  3560. }
  3561. // Instance qualifiers
  3562. if (SUCCEEDED(hr))
  3563. {
  3564. IWbemQualifierSet *pQS = NULL;
  3565. hr = pObj->GetQualifierSet(&pQS);
  3566. CReleaseMe r (pQS);
  3567. if (SUCCEEDED(hr))
  3568. hr = FormatBatchInsQfrs(pConn, pScope, dObjectId, dClassId, 0, pQS, iQfrPos, &pQVals, props, iNumProps);
  3569. if (SUCCEEDED(hr))
  3570. {
  3571. bool bToUpdate = false;
  3572. // Insert arrays and embedded objects last...
  3573. for (int i = 0; i < arrObjProps.Size(); i++)
  3574. {
  3575. VARIANT vTemp;
  3576. VariantInit(&vTemp);
  3577. CIMTYPE cimtype;
  3578. // OPTIMIZATION: Retrieve the buffer and write it directly,
  3579. // for all byte arrays.
  3580. if (!_wcsicmp(arrObjProps.GetAt(i), L"__SECURITY_DESCRIPTOR"))
  3581. {
  3582. BYTE *pBuff = NULL;
  3583. long handle;
  3584. hr = ((_IWmiObject *)pObj)->GetPropertyHandleEx(arrObjProps.GetAt(i), 0, NULL, &handle);
  3585. if (SUCCEEDED(hr))
  3586. {
  3587. ULONG uSize = 0;
  3588. hr = ((_IWmiObject *)pObj)->GetArrayPropAddrByHandle(handle, 0, &uSize, (LPVOID *)&pBuff);
  3589. if (SUCCEEDED(hr))
  3590. {
  3591. // Set this in the database
  3592. long why[1];
  3593. unsigned char t;
  3594. SAFEARRAYBOUND aBounds[1];
  3595. aBounds[0].cElements = uSize;
  3596. aBounds[0].lLbound = 0;
  3597. SAFEARRAY* pArray = SafeArrayCreate(VT_UI1, 1, aBounds);
  3598. vTemp.vt = VT_I1;
  3599. for (int i = 0; i < uSize; i++)
  3600. {
  3601. why[0] = i;
  3602. t = pBuff[i];
  3603. hr = SafeArrayPutElement(pArray, why, &t);
  3604. }
  3605. vTemp.vt = VT_ARRAY|VT_UI1;
  3606. V_ARRAY(&vTemp) = pArray;
  3607. cimtype = CIM_UINT8 + CIM_FLAG_ARRAY;
  3608. }
  3609. }
  3610. }
  3611. else
  3612. pObj->Get(arrObjProps.GetAt(i), 0, &vTemp, &cimtype, NULL);
  3613. if (cimtype == CIM_OBJECT)
  3614. {
  3615. bToUpdate = true;
  3616. IUnknown *pTemp = NULL;
  3617. pTemp = V_UNKNOWN(&vTemp);
  3618. if (pTemp)
  3619. {
  3620. DWORD dPropID;
  3621. SQL_ID dNewClassID = dClassId;
  3622. hr = GetSchemaCache()->GetPropertyID(arrObjProps.GetAt(i), dClassId,
  3623. 0, CIM_OBJECT, dPropID, &dNewClassID);
  3624. if (SUCCEEDED(hr))
  3625. hr = InsertArray(pConn, pScope, dObjectId, dClassId, dPropID, vTemp, 0, 0, lpObjectKey, lpPath, dScopeId, cimtype);
  3626. else
  3627. break;
  3628. }
  3629. VariantClear(&vTemp);
  3630. }
  3631. else // Its an array, a blob, or a very long string.
  3632. {
  3633. DWORD dPropID;
  3634. SQL_ID dNewClassID = dClassId;
  3635. hr = GetSchemaCache()->GetPropertyID(arrObjProps.GetAt(i),
  3636. dClassId, 0, cimtype, dPropID, &dNewClassID);
  3637. if (SUCCEEDED(hr))
  3638. {
  3639. if (!_wcsicmp(arrObjProps.GetAt(i), L"__SECURITY_DESCRIPTOR"))
  3640. {
  3641. hr = TestSD(&vTemp);
  3642. if(FAILED(hr))
  3643. {
  3644. VariantClear( &vTemp );
  3645. break;
  3646. }
  3647. }
  3648. hr = InsertArray(pConn, pScope, dObjectId, dClassId, dPropID, vTemp, 0, 0, lpObjectKey, lpPath, dScopeId, cimtype);
  3649. if (SUCCEEDED(hr) && !_wcsicmp(arrObjProps.GetAt(i), L"__SECURITY_DESCRIPTOR"))
  3650. {
  3651. ((CWmiDbController *)m_pController)->AddSecurityDescriptor(dObjectId);
  3652. // Is this an instance of __ThisNamespace? We need to copy this SD to the current scope object
  3653. if (dClassId == THISNAMESPACEID)
  3654. {
  3655. hr = InsertArray(pConn, pScope, dScopeId, NAMESPACECLASSID, dPropID, vTemp, 0, 0, NULL, NULL, 0, cimtype);
  3656. if (SUCCEEDED(hr))
  3657. ((CWmiDbController *)m_pController)->AddSecurityDescriptor(dScopeId);
  3658. }
  3659. }
  3660. }
  3661. VariantClear( &vTemp );
  3662. }
  3663. if (FAILED(hr))
  3664. break;
  3665. }
  3666. if (SUCCEEDED(hr) && iQfrPos)
  3667. hr = CSQLExecProcedure::InsertBatch (pConn, dObjectId, dClassId, dScopeId, pQVals, iQfrPos);
  3668. }
  3669. }
  3670. }
  3671. if (SUCCEEDED(hr))
  3672. {
  3673. if ((dClassId == NAMESPACECLASSID || GetSchemaCache()->IsDerivedClass(NAMESPACECLASSID, dClassId)))
  3674. {
  3675. hr = GetSchemaCache()->AddNamespace(lpPath, lpObjectKey, dObjectId, dScopeId, dClassId);
  3676. CSQLExecProcedure::InsertScopeMap(pConn, dObjectId, lpPath, dScopeId);
  3677. }
  3678. if (bRemoveSD)
  3679. {
  3680. ((CWmiDbController *)m_pController)->RemoveSecurityDescriptor(dObjectId);
  3681. if (dClassId == THISNAMESPACEID)
  3682. ((CWmiDbController *)m_pController)->RemoveSecurityDescriptor(dScopeId);
  3683. }
  3684. }
  3685. delete pQVals;
  3686. return hr;
  3687. }
  3688. //***************************************************************************
  3689. //
  3690. // CWmiDbSession::FormatBatchInsQfrs
  3691. //
  3692. //***************************************************************************
  3693. HRESULT CWmiDbSession::FormatBatchInsQfrs (CSQLConnection *pConn,IWmiDbHandle *pScope, SQL_ID dObjectId, SQL_ID dClassId,
  3694. DWORD dPropID, IWbemQualifierSet *pQS,
  3695. int &iPos, InsertQfrValues **ppVals, Properties &props, int &iNumProps)
  3696. {
  3697. HRESULT hr = WBEM_S_NO_ERROR;
  3698. BSTR strTemp;
  3699. VARIANT vTemp;
  3700. long lTemp;
  3701. InsertQfrValues *pVals = *ppVals;
  3702. pQS->BeginEnumeration(0);
  3703. while (pQS->Next(0, &strTemp, &vTemp, &lTemp) == S_OK)
  3704. {
  3705. CFreeMe f (strTemp);
  3706. // Don't bother with unstorable qualifiers.
  3707. if (lTemp & (WBEM_FLAVOR_ORIGIN_SYSTEM+WBEM_FLAVOR_ORIGIN_PROPAGATED+WBEM_FLAVOR_AMENDED))
  3708. {
  3709. VariantClear(&vTemp);
  3710. continue;
  3711. }
  3712. lTemp &= ~WBEM_FLAVOR_ORIGIN_PROPAGATED&~WBEM_FLAVOR_ORIGIN_SYSTEM&~WBEM_FLAVOR_AMENDED;
  3713. // Each qualifier, if not found in the cache,
  3714. // will need to be inserted...
  3715. DWORD dQfrID =0;
  3716. CIMTYPE ct = 0;
  3717. switch((vTemp.vt & (0xFFF)))
  3718. {
  3719. case VT_BSTR:
  3720. ct = CIM_STRING;
  3721. break;
  3722. case VT_R8:
  3723. case VT_R4:
  3724. ct = CIM_REAL64;
  3725. break;
  3726. case VT_BOOL:
  3727. ct = CIM_BOOLEAN;
  3728. break;
  3729. default:
  3730. ct = CIM_UINT32;
  3731. break;
  3732. }
  3733. if (FAILED(GetSchemaCache()->GetPropertyID(strTemp, 1,
  3734. REPDRVR_FLAG_QUALIFIER, ct, dQfrID)))
  3735. {
  3736. hr = InsertQualifier (pConn, pScope, dObjectId,strTemp, vTemp, lTemp, 0, dPropID,props);
  3737. if (FAILED(hr))
  3738. {
  3739. VariantClear(&vTemp);
  3740. break;
  3741. }
  3742. }
  3743. if (FAILED(GetSchemaCache()->GetPropertyID(strTemp, 1,
  3744. REPDRVR_FLAG_QUALIFIER, ct, dQfrID)))
  3745. continue;
  3746. if (iPos == iNumProps)
  3747. {
  3748. pVals = ReAllocQfrValues (pVals, iNumProps, iNumProps+10);
  3749. iNumProps += 10;
  3750. if (!pVals)
  3751. {
  3752. VariantClear(&vTemp);
  3753. return WBEM_E_OUT_OF_MEMORY;
  3754. }
  3755. *ppVals = pVals;
  3756. }
  3757. // Add this ID to the batch...
  3758. hr = FormatBatchInsQfrValues(pConn, pScope, dObjectId, dQfrID, vTemp, lTemp,
  3759. pVals, props, iPos, dPropID);
  3760. VariantClear(&vTemp);
  3761. if (FAILED(hr))
  3762. break;
  3763. }
  3764. pQS->EndEnumeration();
  3765. return hr;
  3766. }
  3767. //***************************************************************************
  3768. //
  3769. // CWmiDbSession::FormatBatchInsQfrValues
  3770. //
  3771. //***************************************************************************
  3772. HRESULT CWmiDbSession::FormatBatchInsQfrValues(CSQLConnection *pConn,IWmiDbHandle *pScope,
  3773. SQL_ID dObjectId, DWORD dwQfrID,
  3774. VARIANT &vTemp, long lFlavor, InsertQfrValues *pVals, Properties &props,
  3775. int &iPos, DWORD PropID)
  3776. {
  3777. if (!m_pController ||
  3778. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  3779. return WBEM_E_SHUTTING_DOWN;
  3780. HRESULT hr = WBEM_S_NO_ERROR;
  3781. bool bArray = false;
  3782. if (vTemp.vt & VT_ARRAY)
  3783. bArray = true;
  3784. if (!bArray)
  3785. {
  3786. LPWSTR lpVal = GetStr(vTemp);
  3787. CDeleteMe <wchar_t> r1 (lpVal);
  3788. pVals[iPos].iPos = 0;
  3789. pVals[iPos].iPropID = dwQfrID;
  3790. pVals[iPos].pValue = (lpVal ? new wchar_t [wcslen(lpVal)+1] : NULL);
  3791. pVals[iPos].pRefKey = NULL;
  3792. pVals[iPos].bLong = false;
  3793. if (lpVal)
  3794. wcscpy(pVals[iPos].pValue, lpVal);
  3795. pVals[iPos].iFlavor = lFlavor;
  3796. pVals[iPos].iQfrID = PropID;
  3797. pVals[iPos].dClassId = 1; // always, for qualifiers.
  3798. pVals[iPos].bIndexed = false; // never indexed
  3799. switch(vTemp.vt)
  3800. {
  3801. case VT_BSTR:
  3802. pVals[iPos].iStorageType = WMIDB_STORAGE_STRING;
  3803. break;
  3804. case VT_R4:
  3805. case VT_R8:
  3806. pVals[iPos].iStorageType = WMIDB_STORAGE_REAL;
  3807. break;
  3808. default:
  3809. pVals[iPos].iStorageType = WMIDB_STORAGE_NUMERIC;
  3810. break;
  3811. }
  3812. iPos++;
  3813. }
  3814. else
  3815. hr = InsertArray(pConn, pScope, dObjectId, 0, dwQfrID, vTemp, lFlavor, PropID);
  3816. return hr;
  3817. }
  3818. //***************************************************************************
  3819. //
  3820. // CWmiDbSession::DeleteObject
  3821. //
  3822. //***************************************************************************
  3823. HRESULT STDMETHODCALLTYPE CWmiDbSession::DeleteObject(
  3824. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  3825. /* [in] */ DWORD dwFlags,
  3826. /* [in] */ REFIID riid,
  3827. /* [iid_is][in] */ LPVOID pObjToPut)
  3828. {
  3829. HRESULT hr = WBEM_S_NO_ERROR;
  3830. if (!m_pController ||
  3831. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  3832. return WBEM_E_SHUTTING_DOWN;
  3833. if (!pObjToPut || !pScope)
  3834. return WBEM_E_INVALID_PARAMETER;
  3835. if (dwFlags & ~WMIDB_DISABLE_EVENTS & ~WMIDB_FLAG_ADMIN_VERIFIED)
  3836. return WBEM_E_INVALID_PARAMETER;
  3837. if (riid != IID_IWbemClassObject &&
  3838. riid != IID_IWmiDbHandle &&
  3839. riid != IID__IWmiObject &&
  3840. riid != IID_IWbemPath)
  3841. return WBEM_E_NOT_SUPPORTED;
  3842. SQL_ID dScopeId, dScopeClassId, dClassId, dObjectId;
  3843. LPWSTR lpClass = NULL, lpNamespace = NULL;
  3844. _IWmiObject *pObj = NULL;
  3845. try
  3846. {
  3847. {
  3848. _WMILockit lkt(GetCS());
  3849. if (!((CWmiDbController *)m_pController)->m_bCacheInit)
  3850. {
  3851. hr = LoadSchemaCache();
  3852. if (SUCCEEDED(hr))
  3853. ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE;
  3854. else
  3855. return hr;
  3856. }
  3857. }
  3858. // If this is the __Instances container
  3859. // reject this operation..
  3860. if (GetSchemaCache()->IsDerivedClass
  3861. (INSTANCESCLASSID, ((CWmiDbHandle *)pScope)->m_dClassId) ||
  3862. ((CWmiDbHandle *)pScope)->m_dClassId == INSTANCESCLASSID)
  3863. return WBEM_E_INVALID_OPERATION;
  3864. // We only really support IWmiDbHandles and IWbemPaths
  3865. CSQLConnection *pConn = NULL;
  3866. if (SUCCEEDED(hr))
  3867. {
  3868. AddRef_Lock();
  3869. IWmiDbHandle *pHandle = NULL;
  3870. IWbemPath *pPath = 0;
  3871. if (riid == IID_IWmiDbHandle)
  3872. {
  3873. pHandle = (IWmiDbHandle *)pObjToPut;
  3874. if (pHandle)
  3875. {
  3876. dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  3877. dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId;
  3878. dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId;
  3879. dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId;
  3880. if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  3881. hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId,
  3882. GetSchemaCache()->GetWriteToken(dObjectId, dClassId));
  3883. if (SUCCEEDED(hr))
  3884. {
  3885. hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed());
  3886. if (SUCCEEDED(hr))
  3887. {
  3888. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  3889. hr = IssueDeletionEvents(pConn, dObjectId, dClassId, dScopeId, NULL);
  3890. if (!((CWmiDbHandle *)pHandle)->m_bDefault)
  3891. hr = CustomDelete(pConn, pScope, pHandle);
  3892. hr = Delete(pHandle, pConn);
  3893. GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
  3894. }
  3895. }
  3896. }
  3897. }
  3898. else if (riid == IID_IWbemPath)
  3899. {
  3900. pPath = (IWbemPath *)pObjToPut;
  3901. if (pPath)
  3902. {
  3903. hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE|WMIDB_HANDLE_TYPE_EXCLUSIVE, &pHandle);
  3904. CReleaseMe r2 (pHandle);
  3905. if (SUCCEEDED(hr))
  3906. {
  3907. dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  3908. dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId;
  3909. dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId;
  3910. dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId;
  3911. if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  3912. hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId,
  3913. GetSchemaCache()->GetWriteToken(dObjectId, dClassId));
  3914. if (SUCCEEDED(hr))
  3915. {
  3916. hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed());
  3917. if (SUCCEEDED(hr))
  3918. {
  3919. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  3920. hr = IssueDeletionEvents(pConn, dObjectId, dClassId, dScopeId, NULL);
  3921. if (!((CWmiDbHandle *)pHandle)->m_bDefault)
  3922. hr = CustomDelete(pConn, pScope, pHandle);
  3923. hr = Delete(pHandle, pConn);
  3924. GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
  3925. }
  3926. }
  3927. }
  3928. }
  3929. }
  3930. else if (riid == IID_IWbemClassObject ||
  3931. riid == IID__IWmiObject)
  3932. {
  3933. pObj = (_IWmiObject *)pObjToPut;
  3934. if (pObj)
  3935. {
  3936. lpClass = GetPropertyVal(L"__Class", pObj);
  3937. LPWSTR lpPath = GetPropertyVal(L"__RelPath", pObj);
  3938. if (lpPath)
  3939. {
  3940. hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER,
  3941. IID_IWbemPath, (LPVOID *) &pPath);
  3942. CReleaseMe r2 (pPath);
  3943. if (SUCCEEDED(hr))
  3944. {
  3945. pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, lpPath);
  3946. hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE|WMIDB_HANDLE_TYPE_EXCLUSIVE, &pHandle);
  3947. CReleaseMe r3 (pHandle);
  3948. if (SUCCEEDED(hr))
  3949. {
  3950. dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  3951. dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId;
  3952. dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId;
  3953. dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId;
  3954. if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  3955. hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId,
  3956. GetSchemaCache()->GetWriteToken(dObjectId, dClassId));
  3957. if (SUCCEEDED(hr))
  3958. {
  3959. hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed());
  3960. if (SUCCEEDED(hr))
  3961. {
  3962. if(!(dwFlags & WMIDB_DISABLE_EVENTS))
  3963. hr = IssueDeletionEvents(pConn, dObjectId, dClassId, dScopeId, (IWbemClassObject *)pObj);
  3964. if (!((CWmiDbHandle *)pHandle)->m_bDefault)
  3965. hr = CustomDelete(pConn, pScope, pHandle);
  3966. hr = Delete(pHandle, pConn);
  3967. GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
  3968. }
  3969. }
  3970. }
  3971. }
  3972. }
  3973. }
  3974. }
  3975. else
  3976. hr = WBEM_E_NOT_SUPPORTED;
  3977. if (!IsDistributed() && !(dwFlags & WMIDB_DISABLE_EVENTS) )
  3978. {
  3979. if (SUCCEEDED(hr))
  3980. ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath);
  3981. }
  3982. UnlockDynasties();
  3983. }
  3984. }
  3985. catch (...)
  3986. {
  3987. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::DeleteObject\n"));
  3988. hr = WBEM_E_CRITICAL_ERROR;
  3989. }
  3990. return hr;
  3991. }
  3992. //***************************************************************************
  3993. //
  3994. // CWmiDbSession::IssueDeletionEvents
  3995. //
  3996. //***************************************************************************
  3997. HRESULT CWmiDbSession::IssueDeletionEvents (CSQLConnection *pConn, SQL_ID dObjectId,
  3998. SQL_ID dClassId, SQL_ID dScopeId, IWbemClassObject *_pObj)
  3999. {
  4000. HRESULT hr = WBEM_S_NO_ERROR;
  4001. if (((CWmiDbController *)m_pController)->m_bESSEnabled)
  4002. {
  4003. if (_pObj)
  4004. _pObj->AddRef();
  4005. // The rules:
  4006. // Instance: we don't issue a deletion event for any subobjects, period.
  4007. // Class: issue delete events for all subclasses, not instances
  4008. DWORD dwGenus = 1;
  4009. if (dClassId != 1)
  4010. dwGenus = 2;
  4011. IWbemClassObject *pObj = _pObj;
  4012. if (!pObj)
  4013. {
  4014. // Get the object.
  4015. if (FAILED(GetObjectCache()->GetObject(dObjectId, &pObj, NULL)))
  4016. {
  4017. DWORD dwTemp;
  4018. hr = GetObjectData(pConn, dObjectId, dClassId, dScopeId,
  4019. WMIDB_HANDLE_TYPE_EXCLUSIVE, dwTemp, &pObj, FALSE, NULL);
  4020. }
  4021. }
  4022. CReleaseMe r (pObj);
  4023. // FIXME: Need to handle custom repdrvr deletion events!
  4024. if (!pObj)
  4025. return WBEM_S_NO_ERROR;
  4026. // Get the namespace.
  4027. _bstr_t sNamespace, sClass;
  4028. GetSchemaCache()->GetNamespaceName(dScopeId, &sNamespace);
  4029. if (!_wcsicmp(sNamespace, L"root"))
  4030. sNamespace = L"";
  4031. _bstr_t sPath;
  4032. SQL_ID dTemp1, dTemp2;
  4033. DWORD dwTemp;
  4034. if (dwGenus == 1)
  4035. GetSchemaCache()->GetClassInfo (dObjectId, sPath, dTemp1, dTemp2, dwTemp, &sClass);
  4036. else
  4037. GetSchemaCache()->GetClassInfo (dClassId, sPath, dTemp1, dTemp2, dwTemp, &sClass);
  4038. ((CWmiDbController *)m_pController)->ESSMgr.AddDeleteRecord(pConn, m_sGUID, sNamespace, sClass, dwGenus, pObj);
  4039. // If this is a class, enumerate
  4040. // subclasses and issue deletion events
  4041. if (dwGenus == 1)
  4042. {
  4043. SQL_ID *pIDs = NULL;
  4044. int iNumDerived = 0;
  4045. hr = GetSchemaCache()->GetDerivedClassList(dObjectId, &pIDs, iNumDerived);
  4046. if (SUCCEEDED(hr))
  4047. {
  4048. for (int i = 0; i < iNumDerived; i++)
  4049. {
  4050. IWbemClassObject *pOldObj = NULL;
  4051. hr = GetClassObject(pConn, pIDs[i], &pOldObj);
  4052. CReleaseMe r (pOldObj);
  4053. if (SUCCEEDED(hr))
  4054. {
  4055. LPWSTR lpClassName = GetPropertyVal(L"__Class", pOldObj);
  4056. CDeleteMe <wchar_t> d2 (lpClassName);
  4057. ((CWmiDbController *)m_pController)->ESSMgr.AddDeleteRecord(pConn, m_sGUID,
  4058. sNamespace, sClass, dwGenus, pOldObj);
  4059. }
  4060. }
  4061. delete pIDs;
  4062. }
  4063. if (GetSchemaCache()->IsDerivedClass(dObjectId, NAMESPACECLASSID))
  4064. {
  4065. // If this is a class derived from __Namespace,
  4066. // we have to enumerate the INSTANCES and issue events for them
  4067. // ============================================================
  4068. }
  4069. }
  4070. }
  4071. return hr;
  4072. }
  4073. //***************************************************************************
  4074. //
  4075. // CWmiDbSession::RenameObject
  4076. //
  4077. //***************************************************************************
  4078. HRESULT STDMETHODCALLTYPE CWmiDbSession::RenameObject(
  4079. /* [in] */ IWbemPath __RPC_FAR *pOldPath,
  4080. /* [in] */ IWbemPath __RPC_FAR *pNewPath,
  4081. /* [in] */ DWORD dwFlags,
  4082. /* [in] */ DWORD dwRequestedHandleType,
  4083. /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult)
  4084. {
  4085. HRESULT hr = WBEM_S_NO_ERROR;
  4086. IWmiDbHandle *pRet = NULL;
  4087. if (!m_pController ||
  4088. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4089. return WBEM_E_SHUTTING_DOWN;
  4090. if (!pOldPath || !pNewPath)
  4091. return WBEM_E_INVALID_PARAMETER;
  4092. // This has to handle moving an object from one scope or namespace
  4093. // to another, as well as renaming the keys.
  4094. // Moving from one container to another does not work.
  4095. try
  4096. {
  4097. ULONGLONG uIsInstance1 = 0, uIsInstance2 = 0;
  4098. hr = pOldPath->GetInfo(0, &uIsInstance1);
  4099. hr = pNewPath->GetInfo(0, &uIsInstance2);
  4100. if (!(uIsInstance1 & WBEMPATH_INFO_IS_INST_REF) || !(uIsInstance2 & WBEMPATH_INFO_IS_INST_REF))
  4101. hr = WBEM_E_INVALID_OPERATION;
  4102. else
  4103. {
  4104. DWORD dwLen = 512;
  4105. wchar_t wClass1 [512], wClass2[512];
  4106. hr = pOldPath->GetClassName(&dwLen, wClass1);
  4107. hr = pNewPath->GetClassName(&dwLen, wClass2);
  4108. if (wcscmp(wClass1, wClass2))
  4109. hr = WBEM_E_INVALID_OPERATION;
  4110. else
  4111. {
  4112. IWmiDbHandle *pOld = NULL;
  4113. IWmiDbHandle *pNewScope = NULL;
  4114. LPWSTR lpOldPath, lpOldKey, lpNewPath, lpNewKey;
  4115. hr = NormalizeObjectPathGet(NULL, pOldPath, &lpOldPath);
  4116. if (FAILED(hr))
  4117. goto Exit;
  4118. CDeleteMe <wchar_t> d10(lpOldPath);
  4119. hr = GetObject_Internal(lpOldPath, 0, WMIDB_HANDLE_TYPE_VERSIONED, NULL, &pOld);
  4120. if (FAILED(hr))
  4121. goto Exit;
  4122. CReleaseMe r (pOld);
  4123. if (SUCCEEDED(hr))
  4124. {
  4125. SQL_ID dScopeID = ((CWmiDbHandle *)pOld)->m_dScopeId;
  4126. _IWmiObject *pObj = NULL;
  4127. hr = pOld->QueryInterface(IID__IWmiObject, (void **)&pObj);
  4128. if (SUCCEEDED(hr))
  4129. {
  4130. CReleaseMe r6 (pObj);
  4131. IWbemPathKeyList *pKeys1 = NULL, *pKeys2 = NULL;
  4132. CWStringArray arrKeys;
  4133. hr = GetSchemaCache()->GetKeys(
  4134. dScopeID, wClass1, arrKeys);
  4135. if (SUCCEEDED(hr))
  4136. {
  4137. hr = pOldPath->GetKeyList(&pKeys1);
  4138. CReleaseMe r4(pKeys1);
  4139. if (FAILED(hr))
  4140. goto Exit;
  4141. hr = pNewPath->GetKeyList(&pKeys2);
  4142. CReleaseMe r5 (pKeys2);
  4143. if (FAILED(hr))
  4144. goto Exit;
  4145. ULONG uOldNum = 0, uNewNum = 0;
  4146. hr = pKeys1->GetCount(&uOldNum);
  4147. if (FAILED(hr))
  4148. goto Exit;
  4149. hr = pKeys2->GetCount(&uNewNum);
  4150. if (FAILED(hr))
  4151. goto Exit;
  4152. if (arrKeys.Size() != uOldNum || arrKeys.Size() != uNewNum)
  4153. {
  4154. hr = WBEM_E_INVALID_OBJECT;
  4155. goto Exit;
  4156. }
  4157. else if (arrKeys.Size() > 0)
  4158. {
  4159. for (int i = 0; i < arrKeys.Size(); i++)
  4160. {
  4161. ULONG uBufSize = 512;
  4162. ULONG ct2 = 0;
  4163. BOOL bFound = FALSE;
  4164. for (ULONG j = 0; j < arrKeys.Size(); j++)
  4165. {
  4166. VARIANT vTemp;
  4167. VariantInit(&vTemp);
  4168. CClearMe c (&vTemp);
  4169. wchar_t wBuff[1024];
  4170. ULONG uBufSize = 1024;
  4171. CIMTYPE ct = 0;
  4172. pObj->Get(arrKeys.GetAt(i), 0, NULL, &ct, NULL);
  4173. hr = pKeys2->GetKey2(j, 0, &uBufSize, wBuff, &vTemp, &ct2);
  4174. if (FAILED(hr))
  4175. goto Exit;
  4176. if (!wcslen(wBuff) || !wcscmp(arrKeys.GetAt(i), wBuff))
  4177. {
  4178. bFound = TRUE;
  4179. hr = pObj->Put(arrKeys.GetAt(i), 0, &vTemp, ct);
  4180. if (FAILED(hr))
  4181. goto Exit;
  4182. break;
  4183. }
  4184. }
  4185. if (!bFound)
  4186. {
  4187. hr = WBEM_E_INVALID_PARAMETER;
  4188. goto Exit;
  4189. }
  4190. }
  4191. }
  4192. else
  4193. hr = WBEM_E_INVALID_OPERATION; // Cannot rename singleton
  4194. }
  4195. if (SUCCEEDED(hr))
  4196. {
  4197. pNewPath->DeleteClassPart(0);
  4198. LPWSTR lpNewScope = NULL;
  4199. hr = NormalizeObjectPathGet(NULL, pNewPath, &lpNewScope);
  4200. if (FAILED(hr))
  4201. goto Exit;
  4202. CDeleteMe <wchar_t> d14 (lpNewScope);
  4203. hr = GetObject_Internal(lpNewScope, 0, WMIDB_HANDLE_TYPE_VERSIONED, NULL, &pNewScope);
  4204. if (FAILED(hr))
  4205. goto Exit;
  4206. if (SUCCEEDED(hr))
  4207. {
  4208. // Create the new object
  4209. if (!dwRequestedHandleType)
  4210. dwRequestedHandleType = WMIDB_HANDLE_TYPE_COOKIE;
  4211. _bstr_t sWaste;
  4212. IWmiDbHandle *pHandle = 0;
  4213. hr = PutObject( pNewScope, IID_IWbemClassObject, pObj, 0, dwRequestedHandleType, &pHandle);
  4214. if (SUCCEEDED(hr))
  4215. {
  4216. // Enumerate the subscopes of the old object,
  4217. IWmiDbIterator *pIt = NULL;
  4218. hr = Enumerate(pOld, 0, WMIDB_HANDLE_TYPE_COOKIE, &pIt);
  4219. if (SUCCEEDED(hr))
  4220. {
  4221. IWbemClassObject *pResult = NULL;
  4222. DWORD dwNum = 0;
  4223. while (pIt->NextBatch(1, 0, 0, 0, IID_IWbemClassObject, &dwNum, (void **)&pResult) == 0)
  4224. {
  4225. hr = PutObject( pHandle, IID_IWbemClassObject, pResult, 0, 0, NULL);
  4226. pResult->Release();
  4227. if (FAILED(hr))
  4228. break;
  4229. }
  4230. pIt->Release();
  4231. }
  4232. ((CWmiDbHandle *)pOld)->m_dwHandleType |= WMIDB_HANDLE_TYPE_CONTAINER;
  4233. // Enumerate any collection members (if this was a collection).
  4234. hr = Enumerate(pOld, 0, WMIDB_HANDLE_TYPE_COOKIE, &pIt);
  4235. if (SUCCEEDED(hr))
  4236. {
  4237. IWbemClassObject *pResult = NULL;
  4238. DWORD dwNum = 0;
  4239. while (pIt->NextBatch(1, 0, 0, 0, IID_IWbemClassObject, &dwNum, (void **)&pResult) == 0)
  4240. {
  4241. hr = PutObject( pHandle, IID_IWbemClassObject, pResult, 0, 0, NULL);
  4242. pResult->Release();
  4243. if (FAILED(hr))
  4244. break;
  4245. }
  4246. pIt->Release();
  4247. }
  4248. // If all that worked, kill the old object. This will leave
  4249. // dangling references, but that's OK.
  4250. if (SUCCEEDED(hr))
  4251. hr = Delete (pOld);
  4252. }
  4253. if (ppResult)
  4254. *ppResult = pHandle;
  4255. else if (pHandle)
  4256. pHandle->Release();
  4257. }
  4258. }
  4259. }
  4260. }
  4261. }
  4262. }
  4263. }
  4264. catch (...)
  4265. {
  4266. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::RenameObject"));
  4267. hr = WBEM_E_CRITICAL_ERROR;
  4268. }
  4269. Exit:
  4270. return hr;
  4271. }
  4272. //***************************************************************************
  4273. //
  4274. // CWmiDbSession::AddObject
  4275. //
  4276. //***************************************************************************
  4277. HRESULT STDMETHODCALLTYPE CWmiDbSession::AddObject(
  4278. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  4279. /* [in] */ IWbemPath __RPC_FAR *pPath,
  4280. /* [in] */ DWORD dwFlags,
  4281. /* [in] */ DWORD dwRequestedHandleType,
  4282. /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult)
  4283. {
  4284. HRESULT hr = WBEM_S_NO_ERROR;
  4285. if (!pScope || !pPath)
  4286. return WBEM_E_INVALID_PARAMETER;
  4287. if (!m_pController ||
  4288. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4289. return WBEM_E_SHUTTING_DOWN;
  4290. if (dwRequestedHandleType & ~WMIDB_HANDLE_TYPE_COOKIE
  4291. &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED
  4292. &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE
  4293. &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE
  4294. &~WMIDB_HANDLE_TYPE_SUBSCOPED&~WMIDB_HANDLE_TYPE_CONTAINER&~ WMIDB_HANDLE_TYPE_SCOPE)
  4295. return WBEM_E_INVALID_PARAMETER;
  4296. try
  4297. {
  4298. {
  4299. _WMILockit lkt(GetCS());
  4300. if (!((CWmiDbController *)m_pController)->m_bCacheInit)
  4301. {
  4302. hr = LoadSchemaCache();
  4303. if (SUCCEEDED(hr))
  4304. ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE;
  4305. else
  4306. return hr;
  4307. }
  4308. }
  4309. if (GetSchemaCache()->IsDerivedClass
  4310. (INSTANCESCLASSID, ((CWmiDbHandle *)pScope)->m_dClassId) ||
  4311. ((CWmiDbHandle *)pScope)->m_dClassId == INSTANCESCLASSID )
  4312. return WBEM_E_INVALID_OPERATION;
  4313. // This needs to add an object as a contained instance.
  4314. // * Create a new instance of __Container_Association
  4315. // * Call PutObject
  4316. IWmiDbHandle *pContainerAssoc = NULL;
  4317. hr = GetObject_Internal(L"__Container_Association", 0, WMIDB_HANDLE_TYPE_VERSIONED,
  4318. NULL, &pContainerAssoc);
  4319. if (SUCCEEDED(hr))
  4320. {
  4321. IWbemClassObject *pClassObj = NULL;
  4322. hr = pContainerAssoc->QueryInterface(IID_IWbemClassObject, (void **)&pClassObj);
  4323. CReleaseMe r1 (pClassObj), r2 (pContainerAssoc);
  4324. if (SUCCEEDED(hr))
  4325. {
  4326. IWbemClassObject *pObj = NULL;
  4327. pClassObj->SpawnInstance(0, &pObj);
  4328. CReleaseMe r (pObj);
  4329. LPWSTR lpContainer = NULL, lpContainee;
  4330. hr = NormalizeObjectPath(pScope, (LPCWSTR)NULL, &lpContainer);
  4331. CDeleteMe <wchar_t> d1 (lpContainer);
  4332. if (SUCCEEDED(hr))
  4333. {
  4334. hr = NormalizeObjectPathGet(NULL, pPath, &lpContainee);
  4335. CDeleteMe <wchar_t> d2 (lpContainee);
  4336. if (SUCCEEDED(hr))
  4337. {
  4338. VARIANT vContainer, vContainee;
  4339. CClearMe c1 (&vContainer), c2 (&vContainee);
  4340. VariantInit(&vContainer);
  4341. VariantInit(&vContainee);
  4342. vContainer.bstrVal = SysAllocString(lpContainer);
  4343. vContainee.bstrVal = SysAllocString(lpContainee);
  4344. vContainer.vt = VT_BSTR;
  4345. vContainee.vt = VT_BSTR;
  4346. hr = pObj->Put(L"Container", 0, &vContainer, CIM_REFERENCE);
  4347. if (SUCCEEDED(hr))
  4348. {
  4349. hr = pObj->Put(L"Containee", 0, &vContainee, CIM_REFERENCE);
  4350. if (SUCCEEDED(hr))
  4351. {
  4352. // Stick this object in the
  4353. // parent's scope.
  4354. SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  4355. IWmiDbHandle *pParentScope = NULL;
  4356. hr = GetObject_Internal(L"..", 0, WMIDB_HANDLE_TYPE_VERSIONED, &dScopeId, &pParentScope);
  4357. CReleaseMe r (pParentScope);
  4358. if (SUCCEEDED(hr))
  4359. hr = PutObject(pParentScope, IID_IWbemClassObject, pObj, dwFlags, dwRequestedHandleType, ppResult);
  4360. }
  4361. }
  4362. }
  4363. }
  4364. }
  4365. }
  4366. }
  4367. catch (...)
  4368. {
  4369. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::AddObject\n"));
  4370. hr = WBEM_E_CRITICAL_ERROR;
  4371. }
  4372. return hr;
  4373. }
  4374. //***************************************************************************
  4375. //
  4376. // CWmiDbSession::RemoveObject
  4377. //
  4378. //***************************************************************************
  4379. HRESULT STDMETHODCALLTYPE CWmiDbSession::RemoveObject(
  4380. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  4381. /* [in] */ IWbemPath __RPC_FAR *pPath,
  4382. /* [in] */ DWORD dwFlags)
  4383. {
  4384. HRESULT hr = WBEM_S_NO_ERROR;
  4385. // This needs to remove an object from the container.
  4386. // * Retrieves the handle to the container association
  4387. // * Calls DeleteObject
  4388. if (!pScope || !pPath)
  4389. return WBEM_E_INVALID_PARAMETER;
  4390. if (!m_pController ||
  4391. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4392. return WBEM_E_SHUTTING_DOWN;
  4393. try
  4394. {
  4395. {
  4396. _WMILockit lkt(GetCS());
  4397. if (!((CWmiDbController *)m_pController)->m_bCacheInit)
  4398. {
  4399. hr = LoadSchemaCache();
  4400. if (SUCCEEDED(hr))
  4401. ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE;
  4402. else
  4403. return hr;
  4404. }
  4405. }
  4406. if (GetSchemaCache()->IsDerivedClass
  4407. (INSTANCESCLASSID, ((CWmiDbHandle *)pScope)->m_dClassId) ||
  4408. ((CWmiDbHandle *)pScope)->m_dClassId == INSTANCESCLASSID)
  4409. return WBEM_E_INVALID_OPERATION;
  4410. LPWSTR lpContainer = NULL, lpContainee;
  4411. hr = NormalizeObjectPath(pScope, (LPCWSTR)NULL, &lpContainer);
  4412. CDeleteMe <wchar_t> d1 (lpContainer);
  4413. if (SUCCEEDED(hr))
  4414. {
  4415. hr = NormalizeObjectPathGet(NULL, pPath, &lpContainee);
  4416. CDeleteMe <wchar_t> d2 (lpContainee);
  4417. wchar_t *pTemp = new wchar_t [wcslen(lpContainer)+wcslen(lpContainee)+50];
  4418. if (pTemp)
  4419. {
  4420. CDeleteMe <wchar_t> d (pTemp);
  4421. swprintf(pTemp, L"__Container_Association.Container='%s',Containee='%s'",
  4422. lpContainer, lpContainee);
  4423. IWbemPath *pPath = NULL;
  4424. hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER,
  4425. IID_IWbemPath, (LPVOID *) &pPath);
  4426. CReleaseMe r8 (pPath);
  4427. if (SUCCEEDED(hr))
  4428. {
  4429. hr = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pTemp);
  4430. IWmiDbHandle *pParentScope = NULL;
  4431. SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  4432. hr = GetObject_Internal(L"..", 0, WMIDB_HANDLE_TYPE_VERSIONED, &dScopeId, &pParentScope);
  4433. CReleaseMe r (pParentScope);
  4434. if (SUCCEEDED(hr))
  4435. hr = DeleteObject(pParentScope, dwFlags, IID_IWbemPath, pPath);
  4436. }
  4437. }
  4438. else
  4439. hr = WBEM_E_OUT_OF_MEMORY;
  4440. }
  4441. }
  4442. catch (...)
  4443. {
  4444. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::RemoveObject\n"));
  4445. hr = WBEM_E_CRITICAL_ERROR;
  4446. }
  4447. return hr;
  4448. }
  4449. //***************************************************************************
  4450. //
  4451. // CWmiDbSession::SetDecoration
  4452. //
  4453. //***************************************************************************
  4454. HRESULT STDMETHODCALLTYPE CWmiDbSession::SetDecoration(
  4455. /* [in] */ LPWSTR lpMachineName,
  4456. /* [in] */ LPWSTR lpNamespacePath)
  4457. {
  4458. HRESULT hr = WBEM_S_NO_ERROR;
  4459. if (!m_pController ||
  4460. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4461. return WBEM_E_SHUTTING_DOWN;
  4462. try
  4463. {
  4464. if (!lpMachineName || !lpNamespacePath)
  4465. hr = WBEM_E_INVALID_PARAMETER;
  4466. else
  4467. {
  4468. m_sMachineName = lpMachineName;
  4469. m_sNamespacePath = lpNamespacePath;
  4470. }
  4471. }
  4472. catch (...)
  4473. {
  4474. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::SetDecoration\n"));
  4475. hr = WBEM_E_CRITICAL_ERROR;
  4476. }
  4477. return hr;
  4478. }
  4479. //***************************************************************************
  4480. //
  4481. // CWmiDbSession::PutObjects
  4482. //
  4483. //***************************************************************************
  4484. HRESULT STDMETHODCALLTYPE CWmiDbSession::PutObjects(
  4485. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  4486. /* [in] */ DWORD dwFlags,
  4487. /* [in] */ DWORD dwHandleType,
  4488. /* [in] */ WMIOBJECT_BATCH __RPC_FAR *pBatch)
  4489. {
  4490. HRESULT hr = WBEM_S_NO_ERROR;
  4491. HRESULT hrRet=0;
  4492. if (!m_pController ||
  4493. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4494. return WBEM_E_SHUTTING_DOWN;
  4495. if (dwHandleType == WMIDB_HANDLE_TYPE_INVALID || !pBatch ||!pScope)
  4496. return WBEM_E_INVALID_PARAMETER;
  4497. if (dwFlags &~WMIDB_FLAG_BEST_EFFORT &~WMIDB_FLAG_ATOMIC
  4498. & ~WBEM_FLAG_CREATE_ONLY & ~WBEM_FLAG_UPDATE_ONLY & ~WBEM_FLAG_CREATE_OR_UPDATE
  4499. & ~WBEM_FLAG_USE_SECURITY_DESCRIPTOR &~ WBEM_FLAG_REMOVE_CHILD_SECURITY)
  4500. return WBEM_E_INVALID_PARAMETER;
  4501. try
  4502. {
  4503. CSQLConnection *pConn = NULL;
  4504. hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed());
  4505. if (SUCCEEDED(hr))
  4506. {
  4507. AddRef_Lock();
  4508. for (int i = 0; i < pBatch->dwArraySize; i++)
  4509. {
  4510. IUnknown *pUnk = (IUnknown *)pBatch->pElements[i].pHandle;
  4511. if (pUnk)
  4512. {
  4513. IWmiDbHandle *pTemp = NULL;
  4514. _bstr_t sWaste;
  4515. hr = PutObject(pConn, pScope, 0, L"", pUnk, dwFlags&~WMIDB_FLAG_BEST_EFFORT&~WMIDB_FLAG_ATOMIC, dwHandleType, sWaste, &pTemp);
  4516. if (SUCCEEDED(hr))
  4517. pBatch->pElements[i].pReturnHandle = pTemp;
  4518. pBatch->pElements[i].hRes = hr;
  4519. }
  4520. else
  4521. {
  4522. pBatch->pElements[i].hRes = WBEM_E_INVALID_PARAMETER;
  4523. hr = WBEM_E_INVALID_PARAMETER;
  4524. }
  4525. if (FAILED(hr) && (dwFlags == WMIDB_FLAG_ATOMIC)) // If one fails, keep going.
  4526. {
  4527. hrRet = hr;
  4528. break;
  4529. }
  4530. else if (FAILED(hr))
  4531. hrRet = WBEM_S_PARTIAL_RESULTS;
  4532. }
  4533. if (FAILED(hr) && !(dwFlags & WMIDB_FLAG_ATOMIC))
  4534. hr = WBEM_S_NO_ERROR;
  4535. GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
  4536. if (!IsDistributed() && !(dwFlags & WMIDB_DISABLE_EVENTS) )
  4537. {
  4538. if (SUCCEEDED(hr))
  4539. ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath);
  4540. }
  4541. UnlockDynasties();
  4542. }
  4543. }
  4544. catch (...)
  4545. {
  4546. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::PutObjects\n"));
  4547. hr = WBEM_E_CRITICAL_ERROR;
  4548. }
  4549. return hrRet;
  4550. }
  4551. //***************************************************************************
  4552. //
  4553. // CWmiDbSession::GetObjects
  4554. //
  4555. //***************************************************************************
  4556. HRESULT STDMETHODCALLTYPE CWmiDbSession::GetObjects(
  4557. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  4558. /* [in] */ DWORD dwFlags,
  4559. /* [in] */ DWORD dwHandleType,
  4560. /* [in, out] */ WMIOBJECT_BATCH __RPC_FAR *pBatch)
  4561. {
  4562. HRESULT hr = WBEM_S_NO_ERROR;
  4563. HRESULT hrRet = 0;
  4564. // This is really just a query, except that we need
  4565. // to set return values in the struct.
  4566. if (!m_pController ||
  4567. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4568. return WBEM_E_SHUTTING_DOWN;
  4569. if (dwHandleType == WMIDB_HANDLE_TYPE_INVALID || !pBatch ||!pScope)
  4570. return WBEM_E_INVALID_PARAMETER;
  4571. if (dwHandleType & ~WMIDB_HANDLE_TYPE_COOKIE
  4572. &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED
  4573. &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE
  4574. &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE
  4575. &~WMIDB_HANDLE_TYPE_SUBSCOPED &~WMIDB_HANDLE_TYPE_SCOPE
  4576. &~WMIDB_HANDLE_TYPE_CONTAINER)
  4577. return WBEM_E_INVALID_PARAMETER;
  4578. if (dwFlags &~WMIDB_FLAG_BEST_EFFORT &~WMIDB_FLAG_ATOMIC & ~WBEM_FLAG_USE_SECURITY_DESCRIPTOR)
  4579. return WBEM_E_INVALID_PARAMETER;
  4580. try
  4581. {
  4582. AddRef_Lock();
  4583. if (SUCCEEDED(hr))
  4584. {
  4585. for (int i = 0; i < pBatch->dwArraySize; i++)
  4586. {
  4587. IWbemPath *pPath = pBatch->pElements[i].pPath;
  4588. IWmiDbHandle *pTemp = NULL;
  4589. hr = GetObject(pScope, pPath, pBatch->pElements[i].dwFlags, dwHandleType, &pTemp);
  4590. if (SUCCEEDED(hr))
  4591. {
  4592. pBatch->pElements[i].pReturnHandle = pTemp;
  4593. pBatch->pElements[i].hRes = hr;
  4594. pBatch->pElements[i].dwFlags = dwFlags;
  4595. }
  4596. if (FAILED(hr) && (dwFlags == WMIDB_FLAG_ATOMIC)) // If one fails, keep going.
  4597. {
  4598. hrRet = hr;
  4599. break;
  4600. }
  4601. else if (FAILED(hr))
  4602. hrRet = WBEM_S_PARTIAL_RESULTS;
  4603. }
  4604. }
  4605. UnlockDynasties();
  4606. }
  4607. catch (...)
  4608. {
  4609. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::GetObjects\n"));
  4610. hr = WBEM_E_CRITICAL_ERROR;
  4611. }
  4612. return hrRet;
  4613. }
  4614. //***************************************************************************
  4615. //
  4616. // CWmiDbSession::DeleteObjects
  4617. //
  4618. //***************************************************************************
  4619. HRESULT STDMETHODCALLTYPE CWmiDbSession::DeleteObjects(
  4620. /* [in] */ IWmiDbHandle __RPC_FAR *pScope,
  4621. /* [in] */ DWORD dwFlags,
  4622. /* [in] */ WMIOBJECT_BATCH __RPC_FAR *pBatch)
  4623. {
  4624. HRESULT hr = WBEM_S_NO_ERROR;
  4625. HRESULT hrRet = 0;
  4626. if (!pBatch || !pScope)
  4627. return WBEM_E_INVALID_PARAMETER;
  4628. if (dwFlags &~WMIDB_FLAG_BEST_EFFORT &~WMIDB_FLAG_ATOMIC &~ WMIDB_FLAG_ADMIN_VERIFIED)
  4629. return WBEM_E_INVALID_PARAMETER;
  4630. if (!m_pController ||
  4631. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4632. return WBEM_E_SHUTTING_DOWN;
  4633. try
  4634. {
  4635. {
  4636. _WMILockit lkt(GetCS());
  4637. if (!((CWmiDbController *)m_pController)->m_bCacheInit)
  4638. {
  4639. hr = LoadSchemaCache();
  4640. if (SUCCEEDED(hr))
  4641. ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE;
  4642. else
  4643. return hr;
  4644. }
  4645. }
  4646. CSQLConnection *pConn = NULL;
  4647. SQL_ID dScopeId, dClassId, dObjectId;
  4648. hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed());
  4649. if (SUCCEEDED(hr))
  4650. {
  4651. AddRef_Lock();
  4652. for (int i = 0; i < pBatch->dwArraySize; i++)
  4653. {
  4654. IUnknown *pUnk = (IUnknown *)pBatch->pElements[i].pHandle;
  4655. if (pUnk)
  4656. {
  4657. IWmiDbHandle *pHandle = NULL;
  4658. if (SUCCEEDED(pUnk->QueryInterface(IID_IWmiDbHandle, (void **)&pHandle)))
  4659. {
  4660. CReleaseMe r (pHandle);
  4661. dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  4662. dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId;
  4663. dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId;
  4664. SQL_ID dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId;
  4665. if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  4666. hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId,
  4667. GetSchemaCache()->GetWriteToken(dObjectId, dClassId));
  4668. if (SUCCEEDED(hr))
  4669. {
  4670. if (!((CWmiDbHandle *)pHandle)->m_bDefault)
  4671. hr = CustomDelete(pConn, pScope, pHandle);
  4672. hr = Delete(pHandle, pConn);
  4673. }
  4674. }
  4675. else
  4676. pBatch->pElements[i].hRes = WBEM_E_INVALID_PARAMETER;
  4677. }
  4678. else if (pBatch->pElements[i].pPath)
  4679. {
  4680. // Problem: We need the binary object path to include the scope!!!
  4681. IWbemPath *pPath = pBatch->pElements[i].pPath;
  4682. if (pPath)
  4683. {
  4684. IWmiDbHandle *pHandle = NULL;
  4685. hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE|WMIDB_HANDLE_TYPE_EXCLUSIVE, &pHandle);
  4686. CReleaseMe r (pHandle);
  4687. if (SUCCEEDED(hr))
  4688. {
  4689. dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  4690. dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId;
  4691. dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId;
  4692. SQL_ID dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId;
  4693. if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED))
  4694. hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId,
  4695. GetSchemaCache()->GetWriteToken(dObjectId, dClassId));
  4696. if (SUCCEEDED(hr))
  4697. {
  4698. if (!((CWmiDbHandle *)pHandle)->m_bDefault)
  4699. hr = CustomDelete(pConn, pScope, pHandle);
  4700. hr = Delete(pHandle, pConn);
  4701. }
  4702. }
  4703. }
  4704. }
  4705. else
  4706. pBatch->pElements[i].hRes = WBEM_E_INVALID_PARAMETER;
  4707. pBatch->pElements[i].hRes = hr;
  4708. if (FAILED(hr) && (dwFlags == WMIDB_FLAG_ATOMIC)) // If one fails, keep going.
  4709. {
  4710. hrRet = hr;
  4711. break;
  4712. }
  4713. else if (FAILED(hr))
  4714. hrRet = WBEM_S_PARTIAL_RESULTS;
  4715. }
  4716. GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
  4717. if (!IsDistributed() && !(dwFlags & WMIDB_DISABLE_EVENTS) )
  4718. {
  4719. if (SUCCEEDED(hr))
  4720. ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath);
  4721. }
  4722. UnlockDynasties();
  4723. }
  4724. }
  4725. catch (...)
  4726. {
  4727. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::DeleteObjects\n"));
  4728. hr = WBEM_E_CRITICAL_ERROR;
  4729. }
  4730. return hrRet;
  4731. }
  4732. //***************************************************************************
  4733. //
  4734. // CWmiDbSession::Begin
  4735. //
  4736. //***************************************************************************
  4737. HRESULT STDMETHODCALLTYPE CWmiDbSession::Begin(
  4738. /* [in] */ ULONG uTimeout,
  4739. /* [in] */ ULONG uFlags,
  4740. /* [in] */ GUID __RPC_FAR *pTransGUID)
  4741. {
  4742. HRESULT hr = WBEM_S_NO_ERROR;
  4743. // There can't be an existing transaction.
  4744. if (m_sGUID.length() > 0)
  4745. return WBEM_E_INVALID_OPERATION;
  4746. if (!m_pController ||
  4747. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4748. return WBEM_E_SHUTTING_DOWN;
  4749. // Get or Create a __Transaction instance for this GUID
  4750. // Transaction state = Pending
  4751. // ================================================
  4752. wchar_t wGUID[128];
  4753. StringFromGUID2(*pTransGUID, wGUID, 128);
  4754. wchar_t wPath[255];
  4755. swprintf(wPath, L"__Transaction.GUID=\"%s\"", (LPCWSTR)wGUID);
  4756. IWmiDbHandle *pHandle = NULL;
  4757. hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle);
  4758. CReleaseMe r1 (pHandle);
  4759. if (SUCCEEDED(hr))
  4760. {
  4761. _IWmiObject *pObj = NULL;
  4762. hr = pObj->QueryInterface(IID__IWmiObject, (void **)&pObj);
  4763. CReleaseMe r2 (pObj);
  4764. if (SUCCEEDED(hr))
  4765. {
  4766. ULONG uState = 0;
  4767. LPWSTR lpTemp = NULL;
  4768. lpTemp = GetPropertyVal(L"State", pObj);
  4769. CDeleteMe <wchar_t> d (lpTemp);
  4770. uState = _wtol(lpTemp);
  4771. //hr = pObj->ReadProp(L"State", 0, sizeof(ULONG), NULL,
  4772. // NULL, NULL, NULL, &uState);
  4773. if (uState > WBEM_TRANSACTION_STATE_PENDING)
  4774. {
  4775. return WBEM_E_ALREADY_EXISTS;
  4776. }
  4777. }
  4778. }
  4779. else
  4780. {
  4781. // Create a new one.
  4782. _IWmiObject *pObj = NULL;
  4783. hr = GetObject_Internal(L"__Transaction", 0, WMIDB_HANDLE_TYPE_COOKIE,
  4784. NULL, &pHandle);
  4785. CReleaseMe r2 (pHandle);
  4786. if (SUCCEEDED(hr))
  4787. {
  4788. hr = pHandle->QueryInterface(IID__IWmiObject, (void **)&pObj);
  4789. if (SUCCEEDED(hr))
  4790. {
  4791. CReleaseMe r3 (pObj);
  4792. IWbemClassObject *pInst2 = NULL;
  4793. pObj->SpawnInstance(0, &pInst2);
  4794. CReleaseMe r (pInst2);
  4795. if (pInst2)
  4796. {
  4797. _IWmiObject *pInst = (_IWmiObject *)pInst2;
  4798. ULONG uTemp = WBEM_TRANSACTION_STATE_PENDING;
  4799. WBEMTime tNow(time(0));
  4800. BSTR sTime = tNow.GetDMTF(TRUE);
  4801. CFreeMe f (sTime);
  4802. pInst->WriteProp(L"GUID", 0, (wcslen(wGUID)*2)+2, 1, CIM_STRING, wGUID);
  4803. pInst->WriteProp(L"State", 0, sizeof(ULONG), 1, CIM_UINT32, &uTemp);
  4804. pInst->WriteProp(L"Start", 0, (wcslen(sTime)*2)+2, 1, CIM_DATETIME, sTime);
  4805. pInst->WriteProp(L"LastUpdate", 0, (wcslen(sTime)*2)+2, 1, CIM_DATETIME, sTime);
  4806. CSQLConnection *pConn = NULL;
  4807. hr = GetSQLCache()->GetConnection(&pConn, FALSE, FALSE);
  4808. if (SUCCEEDED(hr))
  4809. {
  4810. _bstr_t sPath;
  4811. hr = PutObject(pConn, NULL, ROOTNAMESPACEID, L"", pInst, 0, NULL, sPath, NULL, FALSE);
  4812. GetSQLCache()->ReleaseConnection(pConn, hr);
  4813. }
  4814. }
  4815. }
  4816. }
  4817. }
  4818. if (SUCCEEDED(hr))
  4819. {
  4820. m_bIsDistributed = TRUE;
  4821. m_sGUID = wGUID;
  4822. }
  4823. return hr;
  4824. }
  4825. //***************************************************************************
  4826. //
  4827. // CWmiDbSession::Rollback
  4828. //
  4829. //***************************************************************************
  4830. HRESULT STDMETHODCALLTYPE CWmiDbSession::Rollback(
  4831. /* [in] */ ULONG uFlags)
  4832. {
  4833. HRESULT hr = WBEM_S_NO_ERROR;
  4834. if (m_sGUID.length() == 0)
  4835. return WBEM_E_INVALID_OPERATION;
  4836. if (!m_pController ||
  4837. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4838. return WBEM_E_SHUTTING_DOWN;
  4839. // Rollback and release the transaction.
  4840. // ======================================
  4841. CSQLConnection *pConn = NULL;
  4842. hr = GetSQLCache()->GetConnection(&pConn, FALSE, TRUE);
  4843. if (SUCCEEDED(hr))
  4844. {
  4845. GetSQLCache()->FinalRollback(pConn);
  4846. GetSQLCache()->ReleaseConnection(pConn, 0, TRUE);
  4847. }
  4848. else
  4849. return hr;
  4850. AddRef_Lock();
  4851. CleanTransLocks();
  4852. wchar_t wPath[255];
  4853. swprintf(wPath, L"__Transaction.GUID=\"%s\"", (LPCWSTR)m_sGUID);
  4854. m_sGUID = L"";
  4855. m_bIsDistributed = FALSE;
  4856. // __Transaction state = rolled back
  4857. // =================================
  4858. IWmiDbHandle *pHandle = NULL;
  4859. hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle);
  4860. CReleaseMe r1 (pHandle);
  4861. if (SUCCEEDED(hr))
  4862. {
  4863. _IWmiObject *pObj = NULL;
  4864. hr = pHandle->QueryInterface(IID__IWmiObject, (void **)&pObj);
  4865. CReleaseMe r2 (pObj);
  4866. if (SUCCEEDED(hr))
  4867. {
  4868. hr = GetSQLCache()->GetConnection(&pConn, FALSE, FALSE);
  4869. if (SUCCEEDED(hr))
  4870. {
  4871. ULONG uState = WBEM_TRANSACTION_STATE_ROLLED_BACK;
  4872. pObj->WriteProp(L"State", 0, sizeof(ULONG), 1, CIM_UINT32, &uState);
  4873. _bstr_t sPath;
  4874. hr = PutObject(pConn, NULL, ROOTNAMESPACEID, L"", pObj, 0, NULL, sPath, NULL, FALSE);
  4875. GetSQLCache()->ReleaseConnection(pConn, hr);
  4876. }
  4877. }
  4878. }
  4879. // Delete all events and remove all locks.
  4880. if (SUCCEEDED(hr))
  4881. hr = ((CWmiDbController *)m_pController)->ESSMgr.DeleteAll(m_sGUID);
  4882. // Remove any affected dynasties from the cache,
  4883. // to make sure we force a reread from the db.
  4884. UnlockDynasties(TRUE);
  4885. return hr;
  4886. }
  4887. //***************************************************************************
  4888. //
  4889. // CWmiDbSession::Commit
  4890. //
  4891. //***************************************************************************
  4892. HRESULT STDMETHODCALLTYPE CWmiDbSession::Commit(
  4893. /* [in] */ ULONG uFlags)
  4894. {
  4895. HRESULT hr = WBEM_S_NO_ERROR;
  4896. if (m_sGUID.length() == 0)
  4897. return WBEM_E_INVALID_OPERATION;
  4898. if (!m_pController ||
  4899. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4900. return WBEM_E_SHUTTING_DOWN;
  4901. // __Transaction state = EventPlayback
  4902. // Include this as final query.
  4903. // ===================================
  4904. AddRef_Lock();
  4905. wchar_t wPath[255];
  4906. swprintf(wPath, L"__Transaction.GUID=\"%s\"", (LPCWSTR)m_sGUID);
  4907. IWmiDbHandle *pHandle = NULL;
  4908. hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle);
  4909. if (SUCCEEDED(hr))
  4910. {
  4911. _IWmiObject *pObj = NULL;
  4912. hr = pHandle->QueryInterface(IID__IWmiObject, (void **)&pObj);
  4913. CReleaseMe r2 (pObj);
  4914. if (SUCCEEDED(hr))
  4915. {
  4916. CSQLConnection *pConn = NULL;
  4917. hr = GetSQLCache()->GetConnection(&pConn, FALSE, TRUE);
  4918. if (SUCCEEDED(hr))
  4919. {
  4920. ULONG uState = WBEM_TRANSACTION_STATE_EVENT_PLAYBACK;
  4921. pObj->WriteProp(L"State", 0, sizeof(ULONG), 1, CIM_UINT32, &uState);
  4922. _bstr_t sPath;
  4923. hr = PutObject(pConn, NULL, ROOTNAMESPACEID, L"", pObj, 0, NULL, sPath, NULL, FALSE);
  4924. // Commit the transaction in the database
  4925. // ======================================
  4926. if (SUCCEEDED(hr))
  4927. {
  4928. GetSQLCache()->FinalCommit(pConn);
  4929. GetSQLCache()->ReleaseConnection(pConn, hr, TRUE);
  4930. // Commit our events.
  4931. // ==================
  4932. hr = ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath);
  4933. }
  4934. }
  4935. }
  4936. pHandle->Release();
  4937. }
  4938. CleanTransLocks();
  4939. m_sGUID = L"";
  4940. m_bIsDistributed = FALSE;
  4941. if (SUCCEEDED(hr))
  4942. {
  4943. // Transaction state = Completed
  4944. IWmiDbHandle *pHandle2 = NULL;
  4945. hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle2);
  4946. CReleaseMe r3 (pHandle2);
  4947. if (SUCCEEDED(hr))
  4948. {
  4949. _IWmiObject *pObj = NULL;
  4950. hr = pHandle2->QueryInterface(IID__IWmiObject, (void **)&pObj);
  4951. CReleaseMe r2 (pObj);
  4952. if (SUCCEEDED(hr))
  4953. {
  4954. CSQLConnection *pConn = NULL;
  4955. hr = GetSQLCache()->GetConnection(&pConn, FALSE, FALSE);
  4956. if (SUCCEEDED(hr))
  4957. {
  4958. ULONG uState = WBEM_TRANSACTION_STATE_COMPLETED;
  4959. pObj->WriteProp(L"State", 0, sizeof(ULONG), 1, CIM_UINT32, &uState);
  4960. _bstr_t sPath;
  4961. hr = PutObject(pConn, NULL, ROOTNAMESPACEID, L"", pObj, 0, NULL, sPath, NULL, FALSE);
  4962. GetSQLCache()->ReleaseConnection(pConn, hr);
  4963. }
  4964. }
  4965. }
  4966. }
  4967. UnlockDynasties();
  4968. return hr;
  4969. }
  4970. //***************************************************************************
  4971. //
  4972. // CWmiDbSession::QueryState
  4973. //
  4974. //***************************************************************************
  4975. HRESULT STDMETHODCALLTYPE CWmiDbSession::QueryState(
  4976. /* [in] */ ULONG uFlags,
  4977. /* [out] */ ULONG __RPC_FAR *puState)
  4978. {
  4979. HRESULT hr = WBEM_S_NO_ERROR;
  4980. if (m_sGUID.length() == 0)
  4981. return WBEM_E_INVALID_OPERATION;
  4982. if (!m_pController ||
  4983. ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN)
  4984. return WBEM_E_SHUTTING_DOWN;
  4985. // This should be stored in the root namespace.
  4986. wchar_t wPath[255];
  4987. swprintf(wPath, L"__Transaction.GUID=\"%s\"", (LPWSTR)m_sGUID);
  4988. IWmiDbHandle *pHandle = NULL;
  4989. hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle);
  4990. CReleaseMe r1 (pHandle);
  4991. if (SUCCEEDED(hr))
  4992. {
  4993. _IWmiObject *pObj = NULL;
  4994. hr = pHandle->QueryInterface(IID__IWmiObject, (void **)&pObj);
  4995. CReleaseMe r2 (pObj);
  4996. if (SUCCEEDED(hr))
  4997. {
  4998. LPWSTR lpTemp = GetPropertyVal(L"State", pObj);
  4999. CDeleteMe <wchar_t> d (lpTemp);
  5000. *puState = _wtol(lpTemp);
  5001. //hr = pObj->ReadProp(L"State", 0, sizeof(ULONG), NULL,
  5002. // NULL, NULL, NULL, puState);
  5003. }
  5004. }
  5005. return hr;
  5006. }
  5007. //***************************************************************************
  5008. //
  5009. // CWmiDbSession::NormalizeObjectPathGet
  5010. //
  5011. //***************************************************************************
  5012. HRESULT CWmiDbSession::NormalizeObjectPathGet(IWmiDbHandle __RPC_FAR *pScope, IWbemPath __RPC_FAR *pPath,
  5013. LPWSTR * lpNewPath, BOOL *bDefault, SQL_ID *pClassId, SQL_ID *pScopeId, CSQLConnection *pConn)
  5014. {
  5015. HRESULT hr = WBEM_S_NO_ERROR;
  5016. BOOL bNs = FALSE;
  5017. BOOL bDone = FALSE;
  5018. LPWSTR lpTempPath = NULL;
  5019. BOOL bDelete = TRUE;
  5020. BOOL bIsRelative = TRUE;
  5021. SQL_ID dScopeId = 0;
  5022. if (pScope)
  5023. dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
  5024. // For retrieval behavior, we only want to know if
  5025. // the object is found in the default namespace
  5026. // or the custom repository.
  5027. if (bDefault)
  5028. *bDefault = TRUE;
  5029. if (!pPath)
  5030. hr = WBEM_E_INVALID_PARAMETER;
  5031. else
  5032. {
  5033. ULONGLONG uIsInstance = 0;
  5034. hr = pPath->GetInfo(0, &uIsInstance);
  5035. wchar_t wTemp[1];
  5036. DWORD dwLen = 1;
  5037. if (!(uIsInstance & WBEMPATH_INFO_IS_PARENT))
  5038. {
  5039. pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, wTemp);
  5040. if (dwLen)
  5041. {
  5042. dwLen += 1024;
  5043. lpTempPath = new wchar_t [dwLen];
  5044. if (lpTempPath)
  5045. hr = pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, lpTempPath);
  5046. else
  5047. {
  5048. hr = WBEM_E_OUT_OF_MEMORY;
  5049. goto Exit;
  5050. }
  5051. }
  5052. }
  5053. else
  5054. {
  5055. lpTempPath = new wchar_t [4096];
  5056. if (!lpTempPath)
  5057. {
  5058. hr = WBEM_E_OUT_OF_MEMORY;
  5059. goto Exit;
  5060. }
  5061. }
  5062. // First, are we just asking to find the current parent.
  5063. // Special case.
  5064. if (!(uIsInstance & WBEMPATH_INFO_IS_PARENT) && !wcslen(lpTempPath))
  5065. {
  5066. hr = WBEM_E_INVALID_PARAMETER;
  5067. goto Exit;
  5068. }
  5069. if (SUCCEEDED(hr))
  5070. {
  5071. if (uIsInstance & WBEMPATH_INFO_IS_PARENT)
  5072. {
  5073. if (bDefault)
  5074. *bDefault = TRUE;
  5075. if (lpNewPath)
  5076. {
  5077. wcscpy(lpTempPath, L"..");
  5078. *lpNewPath = lpTempPath;
  5079. bDelete = FALSE;
  5080. }
  5081. }
  5082. // This must be a path to an object.
  5083. else
  5084. {
  5085. wchar_t wServer[128];
  5086. ULONG uLen = 128;
  5087. hr = pPath->GetServer(&uLen, wServer);
  5088. if (SUCCEEDED(hr) && wcslen(wServer) > 1)
  5089. bIsRelative = FALSE;
  5090. SQL_ID dClassId = 0;
  5091. WCHAR *pClass = new wchar_t [512];
  5092. if (!pClass)
  5093. hr = WBEM_E_OUT_OF_MEMORY;
  5094. else
  5095. {
  5096. DWORD dwLen = 1024;
  5097. hr = pPath->GetClassName(&dwLen, pClass);
  5098. if (FAILED(hr))
  5099. {
  5100. delete pClass;
  5101. pClass = NULL;
  5102. }
  5103. CDeleteMe <wchar_t> r0 (pClass);
  5104. // We have a valid path (we hope).
  5105. // Go through each namespace and scope
  5106. // until we have hit the instance or class.
  5107. ULONG dwNumNamespaces = 0, dwNumScopes = 0;
  5108. wchar_t wBuff[1024];
  5109. BOOL bNeedSlash = FALSE;
  5110. pPath->GetNamespaceCount(&dwNumNamespaces);
  5111. pPath->GetScopeCount(&dwNumScopes);
  5112. lpTempPath[0] = L'\0';
  5113. // Process the namespaces.
  5114. for (ULONG i = 0; i < dwNumNamespaces; i++)
  5115. {
  5116. dwLen = 1024;
  5117. hr = pPath->GetNamespaceAt(i, &dwLen, wBuff);
  5118. if (SUCCEEDED(hr))
  5119. {
  5120. if (bNeedSlash)
  5121. wcscat(lpTempPath, L"\\");
  5122. else
  5123. bNeedSlash = TRUE;
  5124. wcscat(lpTempPath, wBuff);
  5125. if (!_wcsicmp(lpTempPath, m_sNamespacePath))
  5126. {
  5127. bNeedSlash = FALSE;
  5128. lpTempPath[0] = L'\0';
  5129. }
  5130. }
  5131. }
  5132. if (wcslen(lpTempPath))
  5133. {
  5134. LPWSTR lpKey = GetKeyString(lpTempPath);
  5135. CDeleteMe <wchar_t> r2 (lpKey);
  5136. if (!lpKey || !wcslen(lpKey))
  5137. {
  5138. ERRORTRACE((LOG_WBEMCORE, "Invalid scope text in CWmiDbSession::NormalizeObjectPathGet (%S) \n", lpTempPath));
  5139. hr = WBEM_E_INVALID_PARAMETER;
  5140. goto Exit;
  5141. }
  5142. hr = GetSchemaCache()->GetNamespaceID(lpKey, dScopeId);
  5143. if (FAILED(hr))
  5144. goto Exit;
  5145. }
  5146. // Process scopes.
  5147. if (dwNumScopes)
  5148. dwNumScopes--;
  5149. for ( i = 0; i < dwNumScopes; i++)
  5150. {
  5151. dwLen = 1024;
  5152. IWbemPathKeyList *pScopeKeys = NULL;
  5153. hr = pPath->GetScope(i, &dwLen, wBuff, &pScopeKeys);
  5154. if (SUCCEEDED(hr))
  5155. {
  5156. if (bNeedSlash)
  5157. wcscat(lpTempPath, L":");
  5158. else
  5159. bNeedSlash = TRUE;
  5160. LoadClassInfo(pConn, wBuff, dScopeId, TRUE);
  5161. LPWSTR lpTemp = GetSchemaCache()->GetKeyRoot(wBuff, dScopeId);
  5162. CDeleteMe <wchar_t> d (lpTemp);
  5163. if (lpTemp)
  5164. {
  5165. wcscat(lpTempPath, lpTemp);
  5166. }
  5167. else
  5168. wcscat(lpTempPath, wBuff); // OK.. Could be a remote path
  5169. hr = MakeKeyListString(dScopeId, &((CWmiDbController *)m_pController)->SchemaCache,
  5170. wBuff, pScopeKeys, lpTempPath);
  5171. }
  5172. }
  5173. if (wcslen(lpTempPath))
  5174. {
  5175. LPWSTR lpKey = GetKeyString(lpTempPath);
  5176. CDeleteMe <wchar_t> r2 (lpKey);
  5177. if (!lpKey || !wcslen(lpKey))
  5178. {
  5179. ERRORTRACE((LOG_WBEMCORE, "Invalid scope text in CWmiDbSession::NormalizeObjectPathGet (%S) \n", lpTempPath));
  5180. hr = WBEM_E_INVALID_PARAMETER;
  5181. goto Exit;
  5182. }
  5183. hr = GetSchemaCache()->GetNamespaceID(lpKey, dScopeId);
  5184. if (FAILED(hr))
  5185. goto Exit;
  5186. }
  5187. if (pClass && wcslen(pClass))
  5188. {
  5189. BOOL bDeep = (uIsInstance & WBEMPATH_INFO_IS_INST_REF);
  5190. // Make sure this dynasty is in the cache.
  5191. LoadClassInfo(pConn, pClass, dScopeId, bDeep);
  5192. // If this is a class or instance, process the data
  5193. hr = GetSchemaCache()->GetClassID (pClass,
  5194. dScopeId, dClassId);
  5195. if (SUCCEEDED(hr) && pClass)
  5196. {
  5197. IWbemPathKeyList *pKeyList = NULL;
  5198. if (dClassId == INSTANCESCLASSID &&
  5199. (uIsInstance & WBEMPATH_INFO_IS_INST_REF))
  5200. {
  5201. if (lpNewPath)
  5202. {
  5203. dwLen = 1024;
  5204. hr = pPath->GetKeyList(&pKeyList);
  5205. CReleaseMe r (pKeyList);
  5206. hr = pKeyList->GetKey(0, 0, NULL, NULL, &dwLen, lpTempPath, NULL);
  5207. *lpNewPath = lpTempPath;
  5208. bDelete = FALSE;
  5209. bDone = TRUE;
  5210. }
  5211. }
  5212. else
  5213. {
  5214. // If they specified a path like '__Namespace="root" '...
  5215. if ((!_wcsicmp(pClass, L"__Namespace") ||
  5216. GetSchemaCache()->IsDerivedClass(NAMESPACECLASSID, dClassId))
  5217. && (uIsInstance & WBEMPATH_INFO_IS_INST_REF))
  5218. {
  5219. bNs = TRUE;
  5220. hr = pPath->GetKeyList(&pKeyList);
  5221. CReleaseMe r (pKeyList);
  5222. if (SUCCEEDED(hr))
  5223. {
  5224. dwLen = 1024;
  5225. hr = pKeyList->GetKey(0, 0, NULL, NULL, &dwLen, lpTempPath, NULL);
  5226. }
  5227. }
  5228. else
  5229. {
  5230. if (bNeedSlash)
  5231. wcscat(lpTempPath, L":");
  5232. if (uIsInstance & WBEMPATH_INFO_IS_CLASS_REF)
  5233. wcscat(lpTempPath, pClass);
  5234. else
  5235. {
  5236. LPWSTR lpTemp = GetSchemaCache()->GetKeyRoot(pClass, dScopeId);
  5237. CDeleteMe <wchar_t> d (lpTemp);
  5238. if (lpTemp)
  5239. wcscat(lpTempPath, lpTemp);
  5240. else
  5241. {
  5242. hr = WBEM_E_INVALID_OBJECT_PATH;
  5243. goto Exit;
  5244. }
  5245. }
  5246. if (uIsInstance & WBEMPATH_INFO_IS_CLASS_REF && wcslen(pClass) > 2 && pClass[0] == L'_' && pClass[1] == L'_')
  5247. {
  5248. *lpNewPath = lpTempPath;
  5249. bDelete = FALSE;
  5250. bDone = TRUE;
  5251. }
  5252. else if (uIsInstance & WBEMPATH_INFO_IS_INST_REF)
  5253. {
  5254. hr = pPath->GetKeyList(&pKeyList);
  5255. CReleaseMe r (pKeyList);
  5256. if (SUCCEEDED(hr))
  5257. {
  5258. hr = MakeKeyListString(dScopeId, &((CWmiDbController *)m_pController)->SchemaCache,
  5259. pClass, pKeyList, lpTempPath);
  5260. }
  5261. if (bDefault)
  5262. {
  5263. // Instances of system classes are always default
  5264. // Other instances are whatever their scope is.
  5265. if (wcslen(pClass) >= 2 && pClass[0] == L'_' && pClass[1] == L'_')
  5266. *bDefault = TRUE; // all system classes are default
  5267. else if (pScope) // other instances inherit from the scope.
  5268. *bDefault = ((CWmiDbHandle *)pScope)->m_bDefault;
  5269. }
  5270. }
  5271. }
  5272. }
  5273. }
  5274. else
  5275. {
  5276. if (uIsInstance & WBEMPATH_INFO_IS_INST_REF)
  5277. {
  5278. IWbemPathKeyList *pKeyList = NULL;
  5279. hr = pPath->GetKeyList(&pKeyList);
  5280. CReleaseMe rm1(pKeyList);
  5281. if (SUCCEEDED(hr))
  5282. {
  5283. ULONG uNumKeys = 0;
  5284. hr = pKeyList->GetCount(&uNumKeys);
  5285. if (SUCCEEDED(hr))
  5286. {
  5287. if (!uNumKeys)
  5288. bNs = TRUE;
  5289. }
  5290. }
  5291. else
  5292. bNs = TRUE;
  5293. }
  5294. else
  5295. bNs = TRUE;
  5296. if (bNs)
  5297. {
  5298. if (!wcslen(lpTempPath) && pClass)
  5299. wcscpy(lpTempPath, pClass);
  5300. }
  5301. else
  5302. hr = WBEM_E_NOT_FOUND;
  5303. }
  5304. }
  5305. else
  5306. bNs = TRUE;
  5307. if (bNs)
  5308. {
  5309. // This is a namespace.
  5310. dClassId = NAMESPACECLASSID;
  5311. hr = WBEM_S_NO_ERROR;
  5312. }
  5313. if (dClassId == INSTANCESCLASSID)
  5314. bDone = TRUE;
  5315. if (SUCCEEDED(hr) && !bDone)
  5316. {
  5317. hr = NormalizeObjectPath(pScope, lpTempPath, lpNewPath, bNs, NULL, NULL, pConn, TRUE);
  5318. bDelete = TRUE;
  5319. }
  5320. else if (SUCCEEDED(hr))
  5321. {
  5322. *lpNewPath = lpTempPath;
  5323. bDelete = FALSE;
  5324. }
  5325. if (pClassId)
  5326. *pClassId = dClassId;
  5327. if (pScopeId)
  5328. *pScopeId = dScopeId;
  5329. }
  5330. }
  5331. }
  5332. }
  5333. Exit:
  5334. if (bDelete || FAILED(hr))
  5335. delete lpTempPath;
  5336. return hr;
  5337. }
  5338. //***************************************************************************
  5339. //
  5340. // CWmiDbSession::NormalizeObjectPath
  5341. //
  5342. //***************************************************************************
  5343. HRESULT CWmiDbSession::NormalizeObjectPath(IWmiDbHandle __RPC_FAR *pScope, LPCWSTR lpPath, LPWSTR * lpNewPath,
  5344. BOOL bNamespace, CWbemClassObjectProps **ppProps, BOOL *bDefault,
  5345. CSQLConnection *pConn, BOOL bNoTrunc)
  5346. {
  5347. HRESULT hr = WBEM_S_NO_ERROR;
  5348. IWbemClassObject *pScObj = NULL;
  5349. // For other behavior, we are interested if the
  5350. // object is part of a custom mapping.
  5351. // Don't use our default phony namespace.
  5352. if (pScope && ((CWmiDbHandle *)pScope)->m_dObjectId != ROOTNAMESPACEID)
  5353. {
  5354. DWORD dwTempHandle = ((CWmiDbHandle *)pScope)->m_dwHandleType;
  5355. ((CWmiDbHandle *)pScope)->m_dwHandleType |= WMIDB_HANDLE_TYPE_STRONG_CACHE;
  5356. LoadClassInfo(pConn, ((CWmiDbHandle *)pScope)->m_dClassId, FALSE);
  5357. hr = ((CWmiDbHandle *)pScope)->QueryInterface_Internal(pConn, (void **)&pScObj);
  5358. ((CWmiDbHandle *)pScope)->m_dwHandleType = dwTempHandle;
  5359. }
  5360. CReleaseMe r (pScObj);
  5361. if (SUCCEEDED(hr))
  5362. hr = NormalizeObjectPath(pScObj, pScope, lpPath, lpNewPath, bNamespace, ppProps, bDefault, bNoTrunc);
  5363. return hr;
  5364. }
  5365. //***************************************************************************
  5366. //
  5367. // CWmiDbSession::NormalizeObjectPath
  5368. //
  5369. //***************************************************************************
  5370. HRESULT CWmiDbSession::NormalizeObjectPath(IWbemClassObject __RPC_FAR *pScope, IWmiDbHandle *pScope2, LPCWSTR lpPath, LPWSTR * lpNewPath,
  5371. BOOL bNamespace, CWbemClassObjectProps **ppProps,
  5372. BOOL *bDefault, BOOL bNoTrunc)
  5373. {
  5374. HRESULT hr = WBEM_S_NO_ERROR;
  5375. _WMILockit lkt(GetCS());
  5376. int iSize = 0;
  5377. if (lpPath)
  5378. iSize += wcslen(lpPath);
  5379. iSize += m_sNamespacePath.length();
  5380. LPWSTR lpTemp = NULL;
  5381. // Don't add our phony namespace to the path.
  5382. if (pScope)
  5383. {
  5384. CWbemClassObjectProps *pProps = new CWbemClassObjectProps(this, NULL, pScope,
  5385. &((CWmiDbController *)m_pController)->SchemaCache, ((CWmiDbHandle *)pScope2)->m_dScopeId);
  5386. // Next, *undecorate* it. See if the front
  5387. // matches the default stuff, and if so, strip it off.
  5388. // If it doesn't this is an invalid decoration.
  5389. if (pProps)
  5390. {
  5391. if (pProps->lpRelPath)
  5392. iSize += wcslen(pProps->lpRelPath);
  5393. iSize += 50;
  5394. if (pProps->lpNamespace)
  5395. iSize += wcslen(pProps->lpNamespace)+1;
  5396. lpTemp = new wchar_t [iSize]; // Save this pointer, since we are assigning it to the return value.
  5397. if (lpTemp)
  5398. {
  5399. wcscpy(lpTemp,L"");
  5400. if (pProps->lpNamespace)
  5401. {
  5402. int iLen = wcslen(m_sNamespacePath);
  5403. if (!_wcsnicmp(pProps->lpNamespace, (const wchar_t*)m_sNamespacePath, iLen))
  5404. {
  5405. if (wcslen(pProps->lpNamespace) == iLen)
  5406. {
  5407. wcscpy(pProps->lpNamespace, L"");
  5408. }
  5409. else
  5410. {
  5411. wchar_t *wTmp = new wchar_t [wcslen(pProps->lpNamespace) + 1];
  5412. if (wTmp)
  5413. {
  5414. CDeleteMe <wchar_t> r (wTmp);
  5415. wcscpy(wTmp, pProps->lpNamespace);
  5416. LPWSTR lpTmp = wTmp + iLen + 1;
  5417. wcscpy(lpTemp, lpTmp);
  5418. if (ppProps)
  5419. {
  5420. delete pProps->lpNamespace;
  5421. pProps->lpNamespace = new wchar_t [wcslen(lpTemp)+1];
  5422. if (pProps->lpNamespace)
  5423. wcscpy(pProps->lpNamespace, lpTemp);
  5424. else
  5425. hr = WBEM_E_OUT_OF_MEMORY;
  5426. }
  5427. }
  5428. else
  5429. hr = WBEM_E_OUT_OF_MEMORY;
  5430. }
  5431. }
  5432. else
  5433. hr = WBEM_E_INVALID_NAMESPACE;
  5434. }
  5435. if (SUCCEEDED(hr))
  5436. {
  5437. SQL_ID dClassId = 0;
  5438. GetSchemaCache()->GetClassID (pProps->lpClassName,
  5439. ((CWmiDbHandle *)pScope2)->m_dObjectId, dClassId);
  5440. if (!_wcsicmp(L"__Namespace", pProps->lpClassName) ||
  5441. GetSchemaCache()->IsDerivedClass(NAMESPACECLASSID, dClassId) )
  5442. {
  5443. VARIANT vTemp;
  5444. CClearMe v (&vTemp);
  5445. if (wcslen(lpTemp))
  5446. wcscat(lpTemp, L"\\");
  5447. pScope->Get(L"Name", 0, &vTemp, NULL, NULL);
  5448. if (vTemp.vt == VT_BSTR)
  5449. wcscat(lpTemp, vTemp.bstrVal);
  5450. }
  5451. else
  5452. {
  5453. if (wcslen(lpTemp))
  5454. wcscat(lpTemp, L":");
  5455. if (pProps->lpRelPath)
  5456. {
  5457. wcscat(lpTemp, pProps->lpRelPath);
  5458. }
  5459. else
  5460. hr = WBEM_E_INVALID_OBJECT;
  5461. }
  5462. if (lpPath != NULL)
  5463. {
  5464. int iLen = wcslen(lpTemp);
  5465. BOOL bAppend = TRUE;
  5466. if (!_wcsnicmp(lpPath, lpTemp, iLen))
  5467. {
  5468. int iLen2 = wcslen(lpPath);
  5469. if (iLen2 > iLen)
  5470. {
  5471. if (lpPath[iLen] == L':' ||
  5472. lpPath[iLen] == L'\\')
  5473. bAppend = FALSE;
  5474. }
  5475. else if (iLen2 == iLen)
  5476. bAppend = FALSE;
  5477. }
  5478. if (bAppend)
  5479. {
  5480. if (!bNamespace)
  5481. wcscat(lpTemp, L":");
  5482. else
  5483. wcscat(lpTemp, L"\\");
  5484. wcscat(lpTemp, lpPath);
  5485. }
  5486. else
  5487. wcscpy(lpTemp, lpPath);
  5488. }
  5489. }
  5490. if (SUCCEEDED(hr))
  5491. {
  5492. if (ppProps)
  5493. *ppProps = pProps;
  5494. else
  5495. delete pProps;
  5496. }
  5497. }
  5498. else
  5499. hr = WBEM_E_OUT_OF_MEMORY;
  5500. }
  5501. else
  5502. hr = WBEM_E_OUT_OF_MEMORY;
  5503. }
  5504. else
  5505. {
  5506. if (!lpPath)
  5507. iSize = 20;
  5508. lpTemp = new wchar_t [iSize];
  5509. if (lpTemp)
  5510. {
  5511. if (lpPath)
  5512. wcscpy(lpTemp, lpPath);
  5513. else
  5514. lpTemp[0] = L'\0';
  5515. }
  5516. else
  5517. hr = WBEM_E_OUT_OF_MEMORY;
  5518. }
  5519. if (SUCCEEDED(hr))
  5520. *lpNewPath = lpTemp;
  5521. else
  5522. delete lpTemp;
  5523. return hr;
  5524. }
  5525. //***************************************************************************
  5526. //
  5527. // CWmiDbSession::CleanCache
  5528. //
  5529. //***************************************************************************
  5530. HRESULT CWmiDbSession::CleanCache(SQL_ID dObjId, DWORD dwLockType, void *pObj)
  5531. {
  5532. HRESULT hr = WBEM_S_NO_ERROR;
  5533. hr = ((CWmiDbController *)m_pController)->LockCache.DeleteLock(dObjId, false, dwLockType, true, pObj);
  5534. if (SUCCEEDED(hr))
  5535. {
  5536. // Only remove this item from the cache
  5537. // if we deleted the object itself.
  5538. // ====================================
  5539. if (!dwLockType)
  5540. {
  5541. GetObjectCache()->DeleteObject(dObjId);
  5542. GetSchemaCache()->DeleteClass(dObjId);
  5543. GetSchemaCache()->DeleteNamespace(dObjId);
  5544. }
  5545. }
  5546. return hr;
  5547. }
  5548. //***************************************************************************
  5549. //
  5550. // CWmiDbSession::VerifyObjectLock
  5551. //
  5552. //***************************************************************************
  5553. HRESULT CWmiDbSession::VerifyObjectLock (SQL_ID dObjectId, DWORD dwType, DWORD dwVer)
  5554. {
  5555. HRESULT hr = WBEM_S_NO_ERROR;
  5556. DWORD dwLockType, dwVersion;
  5557. bool bImmediate = true;
  5558. if ((dwType & 0xF0000000) == WMIDB_HANDLE_TYPE_SUBSCOPED)
  5559. bImmediate = false;
  5560. hr = ((CWmiDbController *)m_pController)->LockCache.GetCurrentLock(dObjectId, bImmediate, dwLockType, &dwVersion);
  5561. if (SUCCEEDED(hr))
  5562. {
  5563. // This handle was invalidated by someone else.
  5564. if (!dwType)
  5565. hr = E_HANDLE;
  5566. // This is a versioned handle, which was out-of-date.
  5567. else if ((dwType & 0xF) == WMIDB_HANDLE_TYPE_VERSIONED)
  5568. {
  5569. if (dwVer < dwVersion)
  5570. hr = WBEM_E_HANDLE_OUT_OF_DATE;
  5571. }
  5572. // There is a lock outstanding which has precedence
  5573. // over this one.
  5574. if (((dwLockType & 0xF) == WMIDB_HANDLE_TYPE_PROTECTED ||
  5575. (dwLockType & 0xF) == WMIDB_HANDLE_TYPE_EXCLUSIVE) &&
  5576. ((dwLockType & 0xF) != (dwType & 0xF)))
  5577. hr = WBEM_E_ACCESS_DENIED;
  5578. }
  5579. else
  5580. hr = 0;
  5581. return hr;
  5582. }
  5583. //***************************************************************************
  5584. //
  5585. // CWmiDbSession::ShutDown
  5586. //
  5587. //***************************************************************************
  5588. HRESULT CWmiDbSession::ShutDown ()
  5589. {
  5590. HRESULT hr = WBEM_S_NO_ERROR;
  5591. _WMILockit lkt(GetCS());
  5592. try
  5593. {
  5594. if (m_pController)
  5595. {
  5596. ((CWmiDbController *)m_pController)->ReleaseSession(this);
  5597. m_pController->Release();
  5598. m_pController = NULL;
  5599. }
  5600. }
  5601. catch (...)
  5602. {
  5603. ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::ShutDown\n"));
  5604. hr = WBEM_E_CRITICAL_ERROR;
  5605. }
  5606. return hr;
  5607. }
  5608. //***************************************************************************
  5609. //
  5610. // CWmiDbSession::AddTransLock
  5611. //
  5612. //***************************************************************************
  5613. HRESULT CWmiDbSession::AddTransLock(SQL_ID dObjectId, DWORD dwHandleType)
  5614. {
  5615. HRESULT hr = WBEM_S_NO_ERROR;
  5616. SessionLock *pLock = new SessionLock;
  5617. if (pLock)
  5618. {
  5619. DWORD dwVersion = 0;
  5620. pLock->dObjectId = dObjectId;
  5621. pLock->dwHandleType = dwHandleType;
  5622. m_TransLocks.push_back(pLock);
  5623. }
  5624. else
  5625. hr = WBEM_E_OUT_OF_MEMORY;
  5626. return hr;
  5627. }
  5628. //***************************************************************************
  5629. //
  5630. // CWmiDbSession::CleanTransLocks
  5631. //
  5632. //***************************************************************************
  5633. HRESULT CWmiDbSession::CleanTransLocks()
  5634. {
  5635. HRESULT hr = WBEM_S_NO_ERROR;
  5636. for (int i = 0; i < m_TransLocks.size(); i++)
  5637. {
  5638. SessionLock *pLock = m_TransLocks.at(i);
  5639. if (pLock)
  5640. {
  5641. hr = ((CWmiDbController *)m_pController)->LockCache.DeleteLock(
  5642. pLock->dObjectId, false, pLock->dwHandleType);
  5643. }
  5644. }
  5645. m_TransLocks.clear();
  5646. return hr;
  5647. }
  5648. //***************************************************************************
  5649. //
  5650. // CWmiDbSession::LockExists
  5651. //
  5652. //***************************************************************************
  5653. BOOL CWmiDbSession::LockExists (SQL_ID dObjId)
  5654. {
  5655. BOOL bRet = FALSE;
  5656. for (int i = 0; i < m_TransLocks.size(); i++)
  5657. {
  5658. SessionLock *pLock = m_TransLocks.at(i);
  5659. if (pLock)
  5660. {
  5661. if (pLock->dObjectId == dObjId)
  5662. {
  5663. bRet = TRUE;
  5664. break;
  5665. }
  5666. }
  5667. }
  5668. return bRet;
  5669. }
  5670. //***************************************************************************
  5671. //
  5672. // CWmiDbSession::UnlockDynasties
  5673. //
  5674. //***************************************************************************
  5675. HRESULT CWmiDbSession::UnlockDynasties(BOOL bDelete)
  5676. {
  5677. HRESULT hr = WBEM_S_NO_ERROR;
  5678. _WMILockit lkt(GetCS());
  5679. DWORD dwRefCount = Release_Lock();
  5680. if (!dwRefCount)
  5681. {
  5682. DWORD dwThread = GetCurrentThreadId();
  5683. SQLIDs *pIDs = &m_Dynasties[dwThread];
  5684. // Reference count per object (IWmiDbHandle, IWmiDbIterator)
  5685. // Backup fail-safe for handles and queries.
  5686. if (pIDs)
  5687. {
  5688. for (int i = 0; i < pIDs->size(); i++)
  5689. {
  5690. SQL_ID dClass = pIDs->at(i);
  5691. if (!bDelete)
  5692. GetSchemaCache()->UnlockDynasty(dClass);
  5693. else
  5694. GetSchemaCache()->DeleteDynasty(dClass);
  5695. }
  5696. pIDs->clear();
  5697. }
  5698. SessionDynasties::iterator it = m_Dynasties.find(dwThread);
  5699. if (it != m_Dynasties.end())
  5700. m_Dynasties.erase(it);
  5701. }
  5702. return hr;
  5703. }
  5704. //***************************************************************************
  5705. //
  5706. // CWmiDbSession::DeleteRows
  5707. //
  5708. //***************************************************************************
  5709. HRESULT CWmiDbSession::DeleteRows(IWmiDbHandle *pScope, IWmiDbIterator *pIterator, REFIID iid)
  5710. {
  5711. HRESULT hr = WBEM_S_NO_ERROR;
  5712. CFlexArray arrHandles;
  5713. IUnknown *pRet = NULL;
  5714. DWORD dwNumRet = 0;
  5715. // WARNING: This is NOT SCALABLE!!!!
  5716. // We're doing it this way because ESS expects
  5717. // an event to be fired for each result row of a
  5718. // delete query. This should be optimized by
  5719. // deleting all the results in one go, and notifying
  5720. // ESS that the class had some of its members deleted
  5721. HRESULT hRes = pIterator->NextBatch(1, 0, 0, WMIDB_HANDLE_TYPE_COOKIE,
  5722. iid, &dwNumRet, (void **)&pRet);
  5723. while (SUCCEEDED(hRes) && dwNumRet)
  5724. {
  5725. arrHandles.Add(pRet);
  5726. hRes = pIterator->NextBatch(1, 0, 0, WMIDB_HANDLE_TYPE_COOKIE,
  5727. iid, &dwNumRet, (void **)&pRet);
  5728. }
  5729. // When the iterator returns the last row,
  5730. // it will release the db connection
  5731. if (arrHandles.Size())
  5732. {
  5733. // Transact this operation so we don't fire events until
  5734. // all objects have been deleted.
  5735. int iPos = 0;
  5736. GUID transguid;
  5737. CoCreateGuid(&transguid);
  5738. hr = Begin(0, 0, &transguid);
  5739. if (SUCCEEDED(hr))
  5740. {
  5741. for (iPos = 0; iPos < arrHandles.Size(); iPos++)
  5742. {
  5743. IUnknown *pHandle = (IUnknown *)arrHandles.GetAt(iPos);
  5744. if (FAILED(hr = DeleteObject(pScope, 0, iid, (void *)pHandle)))
  5745. {
  5746. pHandle->Release();
  5747. break;
  5748. }
  5749. pHandle->Release();
  5750. }
  5751. }
  5752. if (SUCCEEDED(hr))
  5753. hr = Commit(0);
  5754. else
  5755. {
  5756. hr = Rollback(0);
  5757. // Clean up the handles that were left over.
  5758. for (int i = iPos+1; i < arrHandles.Size(); i++)
  5759. {
  5760. IUnknown *pHandle = (IUnknown *)arrHandles.GetAt(i);
  5761. pHandle->Release();
  5762. }
  5763. }
  5764. }
  5765. return hr;
  5766. }
  5767. //***************************************************************************
  5768. //
  5769. // CWmiDbSession::AddRef_Lock
  5770. //
  5771. //***************************************************************************
  5772. DWORD CWmiDbSession::AddRef_Lock()
  5773. {
  5774. DWORD dwThreadId = GetCurrentThreadId();
  5775. DWORD dwRefCount = m_ThreadRefCount[dwThreadId];
  5776. InterlockedIncrement((LONG *) &dwRefCount);
  5777. m_ThreadRefCount[dwThreadId] = dwRefCount;
  5778. return dwRefCount;
  5779. }
  5780. //***************************************************************************
  5781. //
  5782. // CWmiDbSession::Release_Lock
  5783. //
  5784. //***************************************************************************
  5785. DWORD CWmiDbSession::Release_Lock()
  5786. {
  5787. DWORD dwThreadId = GetCurrentThreadId();
  5788. DWORD dwRefCount = m_ThreadRefCount[dwThreadId];
  5789. if (dwRefCount > 0)
  5790. InterlockedDecrement((LONG *) &dwRefCount);
  5791. m_ThreadRefCount[dwThreadId] = dwRefCount;
  5792. return dwRefCount;
  5793. }