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

10037 lines
303 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. WBEMNAME.CPP
  5. Abstract:
  6. Implements the COM layer of WINMGMT --- the class representing a namespace.
  7. It is defined in wbemname.h
  8. History:
  9. raymcc 05-Apr-96 Created.
  10. raymcc 23-Apr-00 Whistler extensions
  11. --*/
  12. #include "precomp.h"
  13. #pragma warning (disable : 4786)
  14. #include <wbemcore.h>
  15. #include <map>
  16. #include <vector>
  17. #include <genutils.h>
  18. #include <oahelp.inl>
  19. #include <wqllex.h>
  20. #include <autoptr.h>
  21. #include <comutl.h>
  22. #include <helper.h>
  23. #include "wmiarbitrator.h"
  24. #include "wmifinalizer.h"
  25. #include "wmimerger.h"
  26. #ifdef DBG
  27. TimeTraces gTimeTraceHistory;
  28. CStaticCritSec OperationStat::lock_;
  29. #endif
  30. extern BOOL g_bDontAllowNewConnections;
  31. //***************************************************************************
  32. //
  33. //***************************************************************************
  34. #define WBEM_MASK_DEPTH (WBEM_FLAG_DEEP | WBEM_FLAG_SHALLOW)
  35. #define WBEM_MASK_CREATE_UPDATE (WBEM_FLAG_CREATE_ONLY | WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_CREATE_OR_UPDATE)
  36. bool illFormatedClass2 (const wchar_t * pszSuperclass)
  37. {
  38. for (const wchar_t * p = pszSuperclass; *p != L'\0'; ++p)
  39. {
  40. if (!(isunialphanum (*p) || *p == L'_'))
  41. {
  42. return true; //Ill formated
  43. }
  44. }
  45. return false;
  46. };
  47. HRESULT IsDerivedFromSystem(CWbemObject& obj, bool * result)
  48. {
  49. *result = true;
  50. CVar vClass;
  51. HRESULT hr = obj.GetClassName(&vClass);
  52. if (FAILED(hr)) return hr;
  53. wchar_t * className = vClass.GetLPWSTR();
  54. if (className[0] == L'_') return S_OK;
  55. CVar vDeriv;
  56. hr = obj.GetDerivation(&vDeriv);
  57. if (FAILED(hr)) return hr;
  58. CVarVector *pvTemp = vDeriv.GetVarVector();
  59. for (int j = 0; j < pvTemp->Size(); j++)
  60. {
  61. CVar& vParentName = pvTemp->GetAt(j);
  62. wchar_t * parentName = vParentName.GetLPWSTR();
  63. if (parentName[0] == L'_')
  64. {
  65. return S_OK;
  66. }
  67. }
  68. *result = false;
  69. return S_OK;
  70. };
  71. //***************************************************************************
  72. //
  73. // StripServer
  74. // if the string is \\SOMETHING\namespace1\namespace2
  75. // returns namespace1\namespace2
  76. // but it pre-allocates \\.\ in front of it, so that you can move back the pointer
  77. //
  78. //***************************************************************************
  79. LPWSTR StripServer(LPWSTR pszNamespace)
  80. {
  81. LPWSTR lpRet = NULL;
  82. WCHAR * lpPtr = pszNamespace;
  83. if (*lpPtr == L'\\' || *lpPtr == L'/')
  84. {
  85. lpPtr++;
  86. if (*lpPtr == L'\\' || *lpPtr == L'/')
  87. {
  88. BOOL bSlash = FALSE;
  89. while (*lpPtr)
  90. {
  91. lpPtr++;
  92. if (*lpPtr == L'\\' || *lpPtr == L'/')
  93. {
  94. bSlash = TRUE;
  95. break;
  96. }
  97. }
  98. if (bSlash)
  99. {
  100. lpPtr++;
  101. size_t tmpSize = 4 + wcslen(lpPtr) + 1;
  102. WCHAR * pFull = new WCHAR[tmpSize];
  103. if (NULL == pFull) return pFull;
  104. StringCchCopyW(pFull,tmpSize,L"\\\\.\\");
  105. StringCchCopyW(pFull+4,tmpSize-4,lpPtr);
  106. lpRet = pFull;
  107. }
  108. }
  109. }
  110. if (!lpRet)
  111. {
  112. size_t tmpSize = 4 + wcslen(lpPtr) + 1;
  113. WCHAR * pFull = new WCHAR[tmpSize];
  114. if (NULL == pFull) return pFull;
  115. StringCchCopyW(pFull,tmpSize,L"\\\\.\\");
  116. StringCchCopyW(pFull+4,tmpSize-4,lpPtr);
  117. lpRet = pFull;
  118. }
  119. return lpRet;
  120. }
  121. //
  122. //
  123. //
  124. ///////////////////////////////////////////////////////////////
  125. class CSecureEssNamespaceSink
  126. : public CUnkBase<IWbemObjectSink, &IID_IWbemObjectSink>
  127. {
  128. CWbemPtr<CWbemNamespace> m_pNamespace;
  129. CWbemPtr<IWbemObjectSink> m_pSink;
  130. public:
  131. CSecureEssNamespaceSink( CWbemNamespace* pNamespace,
  132. IWbemObjectSink* pSink )
  133. : m_pNamespace(pNamespace), m_pSink(pSink) {}
  134. STDMETHOD(Indicate)(long lObjectCount, IWbemClassObject** pObjArray)
  135. {
  136. HRESULT hRes = m_pNamespace->CheckNs();
  137. if (FAILED(hRes))
  138. return hRes;
  139. if ( !m_pNamespace->Allowed( WBEM_FULL_WRITE_REP ) )
  140. return WBEM_E_ACCESS_DENIED;
  141. return m_pSink->Indicate( lObjectCount, pObjArray );
  142. }
  143. STDMETHOD(SetStatus)(long a, long b, BSTR c, IWbemClassObject* d)
  144. {
  145. HRESULT hRes = m_pNamespace->CheckNs();
  146. if (FAILED(hRes))
  147. return hRes;
  148. if ( !m_pNamespace->Allowed( WBEM_FULL_WRITE_REP ) )
  149. return WBEM_E_ACCESS_DENIED;
  150. return m_pSink->SetStatus( a, b, c, d );
  151. }
  152. };
  153. //***************************************************************************
  154. //
  155. //***************************************************************************
  156. //
  157. CWbemNamespace::CWbemNamespace()
  158. {
  159. m_uSecondaryRefCount = 0;
  160. m_bShutDown = FALSE;
  161. m_pSession = 0;
  162. m_pDriver = 0;
  163. m_pNsHandle = 0;
  164. m_pScopeHandle = 0;
  165. m_pThisNamespace = 0;
  166. m_pThisNamespaceFull = 0;
  167. m_dwPermission = 0;
  168. m_dwSecurityFlags = 0;
  169. m_wszUserName = 0;
  170. m_bProvider = FALSE;
  171. m_bForClient = FALSE;
  172. m_bESS = FALSE;
  173. m_bSecurityInitialized = FALSE;
  174. m_pProvFact = 0;
  175. m_pCoreSvc = 0;
  176. m_bRepositOnly = FALSE;
  177. m_pRefreshingSvc = NULL;
  178. m_pszClientMachineName = NULL;
  179. m_dwClientProcessID = -1;
  180. m_pArb = CWmiArbitrator::GetRefedArbitrator();
  181. m_pArb->RegisterNamespace((_IWmiCoreHandle *)this);
  182. gClientCounter.AddClientPtr(&m_Entry);
  183. }
  184. //***************************************************************************
  185. //
  186. //***************************************************************************
  187. //
  188. CWbemNamespace *CWbemNamespace::CreateInstance()
  189. {
  190. try
  191. {
  192. if (NULL == CWmiArbitrator::GetUnrefedArbitrator()) return NULL;
  193. CWbemNamespace *pNs = new CWbemNamespace;
  194. if (pNs) pNs->AddRef();
  195. return pNs;
  196. }
  197. catch(CX_Exception &)
  198. {
  199. return 0;
  200. }
  201. }
  202. //***************************************************************************
  203. //
  204. // CWbemNamespace::Initialize
  205. //
  206. // Real constructor. In addition to finding the namespace in the database, this
  207. // function also enumerates all the class providers in the namespace and
  208. // loads them. It also notifies the ESS of the opening.
  209. //
  210. // PARAMETERS:
  211. //
  212. // LPWSTR Namespace The full of the namespace to create.
  213. //
  214. // RETURN VALUES:
  215. //
  216. // Even though this function has no return values, it indicates success
  217. // or failure by setting the Status member variable to the error code.
  218. // WBEM_S_NO_ERROR On Success
  219. // WBEM_E_INVALID_NAMESPACE No such namespace
  220. // WBEM_E_CRITICAL_ERROR Other database error.
  221. //
  222. //***************************************************************************
  223. HRESULT CWbemNamespace::Initialize(
  224. LPWSTR pszNamespace,
  225. LPWSTR wszUserName,
  226. DWORD dwSecFlags,
  227. DWORD dwPermission,
  228. BOOL bForClient,
  229. BOOL bRepositOnly,
  230. LPCWSTR pszClientMachineName,
  231. DWORD dwClientProcessID,
  232. BOOL bSkipSDInitialize,
  233. IWmiDbSession *pParentSession)
  234. {
  235. try
  236. {
  237. m_dwSecurityFlags = dwSecFlags;
  238. m_dwPermission = dwPermission;
  239. if(g_bDontAllowNewConnections)
  240. return WBEM_E_SHUTTING_DOWN;
  241. PSID pRawSid;
  242. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  243. if (!AllocateAndInitializeSid( &id, 2, // SEC:REVIEWED 2002-03-22 : OK
  244. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  245. 0,0,0,0,0,0,&pRawSid))
  246. return WBEM_E_OUT_OF_MEMORY;
  247. CNtSid Sid(pRawSid);
  248. FreeSid( pRawSid );
  249. if (CNtSid::NoError != Sid.GetStatus()) return WBEM_E_OUT_OF_MEMORY;
  250. CNtAce ace(1,ACCESS_ALLOWED_ACE_TYPE,0,Sid);
  251. if(ace.GetStatus() != 0)
  252. return WBEM_E_OUT_OF_MEMORY;
  253. CNtAcl acl;
  254. acl.AddAce(&ace);
  255. m_sdCheckAdmin.SetDacl(&acl);
  256. CNtSid owner(CNtSid::CURRENT_USER);
  257. if (CNtSid::NoError != owner.GetStatus()) return WBEM_E_OUT_OF_MEMORY;
  258. m_sdCheckAdmin.SetGroup(&owner);
  259. m_sdCheckAdmin.SetOwner(&owner);
  260. m_bForClient = bForClient;
  261. m_pThisNamespaceFull = StripServer(pszNamespace);
  262. if(m_pThisNamespaceFull == NULL) return WBEM_E_OUT_OF_MEMORY;
  263. m_pThisNamespace = m_pThisNamespaceFull + 4; // move past "\\.\"
  264. m_pCoreSvc = CCoreServices::CreateInstance();
  265. if(m_pCoreSvc == NULL)
  266. return WBEM_E_OUT_OF_MEMORY;
  267. m_pProvFact = 0;
  268. m_bRepositOnly = bRepositOnly;
  269. // Flip the slashes
  270. // ================
  271. WCHAR* pwc = m_pThisNamespace;
  272. while(*pwc)
  273. {
  274. if(*pwc == '/')
  275. *pwc = '\\';
  276. pwc++;
  277. }
  278. m_wszUserName = (wszUserName?Macro_CloneLPWSTR(wszUserName):NULL);
  279. // Repository binding.
  280. // ===================
  281. m_pNsHandle = 0;
  282. HRESULT hRes;
  283. IWmiDbSession *pTempSession= pParentSession;
  284. if (pTempSession == NULL)
  285. {
  286. hRes = CRepository::GetDefaultSession(&pTempSession);
  287. if (FAILED(hRes)) return hRes;
  288. }
  289. else
  290. pTempSession->AddRef();
  291. CReleaseMe rmSession(pTempSession);
  292. hRes = CRepository::OpenScope(pTempSession, m_pThisNamespace, 0, &m_pDriver, &m_pSession, &m_pScopeHandle, &m_pNsHandle);
  293. if (FAILED(hRes))
  294. {
  295. Status = WBEM_E_INVALID_NAMESPACE;
  296. return hRes;
  297. }
  298. if (m_pScopeHandle == 0)
  299. {
  300. m_bSubscope = FALSE;
  301. m_pScopeHandle = m_pNsHandle;
  302. if(m_pScopeHandle == NULL)
  303. {
  304. ERRORTRACE((LOG_WBEMCORE, "OpenScope returned success, yet m_pNsHandle is null!\n"));
  305. return WBEM_E_CRITICAL_ERROR;
  306. }
  307. m_pScopeHandle->AddRef();
  308. }
  309. else
  310. {
  311. #ifdef DBG
  312. DebugBreak();
  313. #endif
  314. m_bSubscope = TRUE;
  315. return WBEM_E_INVALID_NAMESPACE;
  316. }
  317. m_pProvFact = 0;
  318. if (!bRepositOnly)
  319. {
  320. _IWmiProvSS *pProvSS = 0;
  321. m_pCoreSvc->GetProviderSubsystem(0, &pProvSS);
  322. CReleaseMe _(pProvSS);
  323. if(pProvSS)
  324. {
  325. HRESULT hr = pProvSS->Create(
  326. this, // Stupid because v-table access can occur before constructor completion
  327. 0, // lFlags
  328. 0, // pCtx
  329. m_pThisNamespace, // Path
  330. IID__IWmiProviderFactory,
  331. (LPVOID *) &m_pProvFact
  332. );
  333. if (FAILED(hr)) return hr ;
  334. }
  335. }
  336. if(pszClientMachineName)
  337. {
  338. delete m_pszClientMachineName;
  339. DUP_STRING_NEW(m_pszClientMachineName, pszClientMachineName);
  340. if(m_pszClientMachineName == NULL)
  341. return WBEM_E_OUT_OF_MEMORY;
  342. }
  343. m_dwClientProcessID = dwClientProcessID;
  344. Status = WBEM_S_NO_ERROR;
  345. //Initialize Security descriptor
  346. if (!bSkipSDInitialize)
  347. {
  348. hRes = InitializeSD(pTempSession);
  349. if (FAILED(hRes)) return hRes;
  350. }
  351. m_pCoreSvc->IncrementCounter(WMICORE_SELFINST_CONNECTIONS, 1);
  352. return Status;
  353. }
  354. catch(...)
  355. {
  356. ExceptionCounter c;
  357. return WBEM_E_FAILED;
  358. }
  359. }
  360. //***************************************************************************
  361. //
  362. // CWbemNamespace::~CWbemNamespace
  363. //
  364. // Notifies the ESS of namespace closure and frees up all the class providers.
  365. //
  366. //***************************************************************************
  367. CWbemNamespace::~CWbemNamespace()
  368. {
  369. // do this before releasing the arbitrator
  370. m_pArb->UnregisterNamespace((_IWmiCoreHandle *)this);
  371. if (m_pCoreSvc)
  372. m_pCoreSvc->DecrementCounter(WMICORE_SELFINST_CONNECTIONS, 1);
  373. ReleaseIfNotNULL(m_pProvFact);
  374. ReleaseIfNotNULL(m_pCoreSvc);
  375. ReleaseIfNotNULL(m_pSession);
  376. ReleaseIfNotNULL(m_pDriver);
  377. ReleaseIfNotNULL(m_pNsHandle);
  378. ReleaseIfNotNULL(m_pScopeHandle);
  379. ReleaseIfNotNULL(m_pRefreshingSvc);
  380. ReleaseIfNotNULL(m_pArb);
  381. DeleteAndNull(m_pThisNamespaceFull);
  382. DeleteAndNull(m_wszUserName);
  383. DeleteAndNull(m_pszClientMachineName);
  384. gClientCounter.RemoveClientPtr(&m_Entry);
  385. }
  386. //***************************************************************************
  387. //
  388. // CWbemNamespace::QueryInterface
  389. //
  390. // Exports IWbemServices interface.
  391. //
  392. //***************************************************************************
  393. STDMETHODIMP CWbemNamespace::QueryInterface(
  394. IN REFIID riid,
  395. OUT LPVOID *ppvObj
  396. )
  397. {
  398. *ppvObj = 0;
  399. if (IID_IUnknown==riid || IID_IWbemServices==riid )
  400. {
  401. *ppvObj = (IWbemServices*)this;
  402. AddRef();
  403. return S_OK;
  404. }
  405. else if (IID_IWbemRefreshingServices == riid)
  406. {
  407. CInCritSec ics(&m_cs);
  408. // Check if we already have this one
  409. if ( NULL == m_pRefreshingSvc )
  410. {
  411. IUnknown * pUnk = NULL;
  412. // Aggregate this interface - We MUST use IUnknown, so the aggregee does not AddRef us.
  413. HRESULT hr = CoCreateInstance( CLSID__WbemConfigureRefreshingSvcs, // SEC:REVIEWED 2002-03-22 : OK
  414. (IWbemServices*) this, CLSCTX_INPROC_SERVER,
  415. IID_IUnknown, (void**) &pUnk );
  416. if (FAILED(hr)) return hr;
  417. OnDeleteIf<IUnknown *,void(*)(IUnknown *),RM> rmUnk(pUnk);
  418. _IWbemConfigureRefreshingSvcs* pCfgRefrSvc = NULL;
  419. hr = pUnk->QueryInterface( IID__IWbemConfigureRefreshingSvcs, (void**) &pCfgRefrSvc );
  420. if (FAILED(hr)) return hr;
  421. CReleaseMe rm(pCfgRefrSvc);
  422. // Use BSTR's in case any marshaling takes place
  423. BSTR pstrMachineName = SysAllocString( ConfigMgr::GetMachineName() );
  424. if (NULL == pstrMachineName) return E_OUTOFMEMORY;
  425. CSysFreeMe sfm1( pstrMachineName );
  426. BSTR pstrNamespace = SysAllocString( m_pThisNamespace );
  427. if (NULL == pstrNamespace) return E_OUTOFMEMORY;
  428. CSysFreeMe sfm2( pstrNamespace );
  429. hr = pCfgRefrSvc->SetServiceData( pstrMachineName, pstrNamespace );
  430. if (FAILED(hr)) return hr;
  431. // compensate the Automatic Objects above
  432. m_pRefreshingSvc = pUnk;
  433. rmUnk.dismiss();
  434. }
  435. return m_pRefreshingSvc->QueryInterface( IID_IWbemRefreshingServices, ppvObj );
  436. }
  437. else if(IID_IWbemInternalServices == riid)
  438. {
  439. *ppvObj = (IWbemInternalServices*)this;
  440. AddRef();
  441. return S_OK;
  442. }
  443. return E_NOINTERFACE;
  444. }
  445. //***************************************************************************
  446. //
  447. //***************************************************************************
  448. //
  449. ULONG CWbemNamespace::AddRef()
  450. {
  451. ULONG uNewCount = InterlockedIncrement((LONG *) &m_uSecondaryRefCount);
  452. return uNewCount;
  453. }
  454. //***************************************************************************
  455. //
  456. //***************************************************************************
  457. //
  458. ULONG CWbemNamespace::Release()
  459. {
  460. ULONG uNewCount = InterlockedDecrement((LONG *) &m_uSecondaryRefCount);
  461. if (0 == uNewCount) delete this;
  462. return uNewCount;
  463. }
  464. //***************************************************************************
  465. //
  466. //***************************************************************************
  467. //
  468. HRESULT CWbemNamespace::Dump(FILE *f)
  469. {
  470. // SEC:REVIEWED 2002-03-22 : OK; debugging use only
  471. fprintf(f, "---Namespace = 0x%p----------------------------\n", this); // SEC:REVIEWED 2002-03-22 : OK
  472. fprintf(f, " Secondary Refcount = %d\n", m_uSecondaryRefCount); // SEC:REVIEWED 2002-03-22 : OK
  473. if(m_pThisNamespace)
  474. fprintf(f, " Name = %ls\n", m_pThisNamespace); // SEC:REVIEWED 2002-03-22 : OK
  475. if(m_wszUserName)
  476. fprintf(f, " User Name = %ls\n", m_wszUserName); // SEC:REVIEWED 2002-03-22 : OK
  477. if(m_pszClientMachineName)
  478. fprintf(f, " Client Machine Name = %ls\n", m_pszClientMachineName); // SEC:REVIEWED 2002-03-22 : OK
  479. else
  480. fprintf(f, " Client Machine Name = <unknown>\n"); // SEC:REVIEWED 2002-03-22 : OK
  481. if(m_dwClientProcessID)
  482. fprintf(f, " Client Process = 0X%X\n", m_dwClientProcessID); // SEC:REVIEWED 2002-03-22 : OK
  483. else
  484. fprintf(f, " Client Process = <unknown>\n"); // SEC:REVIEWED 2002-03-22 : OK
  485. return S_OK;
  486. }
  487. //***************************************************************************
  488. //
  489. //***************************************************************************
  490. //
  491. /*
  492. HRESULT CWbemNamespace::SetErrorObj(IWbemClassObject* pErrorObj)
  493. {
  494. if (pErrorObj == NULL)
  495. {
  496. return S_OK;
  497. }
  498. IErrorInfo* pInfo;
  499. HRESULT hRes = pErrorObj->QueryInterface(IID_IErrorInfo, (void**)&pInfo);
  500. if (FAILED(hRes))
  501. return hRes;
  502. hRes = SetErrorInfo(0, pInfo);
  503. pInfo->Release();
  504. return hRes;
  505. }
  506. */
  507. //***************************************************************************
  508. //
  509. // CWbemNamespace::SplitLocalized
  510. //
  511. //***************************************************************************
  512. HRESULT CWbemNamespace::SplitLocalized (
  513. CWbemObject *pOriginal,
  514. CWbemObject *pStoredObj
  515. )
  516. {
  517. HRESULT hres = 0;
  518. CVar vProv;
  519. IWbemQualifierSet *pOrigQs = NULL, *pStoredQs = NULL;
  520. VARIANT vVal;
  521. VariantInit(&vVal);
  522. hres = pOriginal->GetQualifierSet(&pOrigQs);
  523. if (FAILED(hres))
  524. return hres;
  525. if (pStoredObj)
  526. {
  527. hres = pStoredObj->GetQualifierSet(&pStoredQs);
  528. if (FAILED(hres))
  529. {
  530. pOrigQs->Release();
  531. return hres;
  532. }
  533. }
  534. hres = FixAmendedQualifiers(pOrigQs, pStoredQs);
  535. pOrigQs->Release();
  536. pOrigQs = NULL;
  537. if (pStoredQs)
  538. {
  539. pStoredQs->Release();
  540. pStoredQs = NULL;
  541. }
  542. if (SUCCEEDED(hres))
  543. {
  544. pOriginal->BeginEnumeration(0);
  545. LONG lLong;
  546. CIMTYPE ct;
  547. VARIANT vNewVal;
  548. VariantInit(&vNewVal);
  549. BSTR strPropName = NULL;
  550. while((hres = pOriginal->Next(0, &strPropName, &vNewVal, &ct, &lLong)) == S_OK)
  551. {
  552. CSysFreeMe sfm(strPropName);
  553. CClearMe ccm(&vNewVal);
  554. CWStringArray arrDel;
  555. pOrigQs = NULL;
  556. pStoredQs = NULL;
  557. // Ignore system qualifiers.
  558. if (strPropName[0] == L'_')
  559. {
  560. continue;
  561. }
  562. hres = pOriginal->GetPropertyQualifierSet(strPropName, &pOrigQs);
  563. if (FAILED(hres))
  564. {
  565. return hres;
  566. }
  567. pStoredQs = NULL;
  568. if (pStoredObj)
  569. {
  570. pStoredObj->GetPropertyQualifierSet(strPropName, &pStoredQs);
  571. }
  572. hres = FixAmendedQualifiers(pOrigQs, pStoredQs);
  573. pOrigQs->Release();
  574. if (pStoredQs)
  575. pStoredQs->Release();
  576. }
  577. pOriginal->EndEnumeration();
  578. // Unfortunately, we have to enumerate the methods,
  579. // and *then* update them...
  580. BSTR bstrMethodName;
  581. pOriginal->BeginMethodEnumeration(0);
  582. IWbemClassObject *pLIn = NULL, *pLOut = NULL, *pOIn = NULL, *pOOut = NULL;
  583. // first count the number of methods
  584. while ( pOriginal->NextMethod( 0, &bstrMethodName, 0, 0 ) == S_OK )
  585. {
  586. pLIn = pLOut = pOIn = pOOut = NULL;
  587. pOrigQs = NULL ;
  588. pStoredQs = NULL ;
  589. hres = pOriginal->GetMethod(bstrMethodName, 0, &pLIn, &pLOut);
  590. if ( FAILED ( hres ) )
  591. {
  592. continue ;
  593. }
  594. CSysFreeMe fm(bstrMethodName);
  595. CReleaseMe rm0(pLIn);
  596. CReleaseMe rm2(pLOut);
  597. hres = pOriginal->GetMethodQualifierSet(bstrMethodName, &pOrigQs);
  598. if (FAILED(hres))
  599. {
  600. continue;
  601. }
  602. CReleaseMe rm4 ( pOrigQs ) ;
  603. if (pStoredObj)
  604. {
  605. hres = pStoredObj->GetMethodQualifierSet(bstrMethodName, &pStoredQs);
  606. if ( FAILED ( hres ) )
  607. {
  608. continue ;
  609. }
  610. }
  611. CReleaseMe rm5 ( pStoredQs ) ;
  612. // Method qualifiers...
  613. hres = FixAmendedQualifiers(pOrigQs, pStoredQs);
  614. if (SUCCEEDED(hres))
  615. {
  616. if (pStoredObj)
  617. hres = pStoredObj->GetMethod(bstrMethodName, 0, &pOIn, &pOOut);
  618. CReleaseMe rm1(pOIn);
  619. CReleaseMe rm3(pOOut);
  620. if (pLIn)
  621. hres = SplitLocalized((CWbemObject *)pLIn, (CWbemObject *)pOIn);
  622. if (pLOut)
  623. hres = SplitLocalized((CWbemObject *)pLOut, (CWbemObject *)pOOut);
  624. hres = pOriginal->PutMethod(bstrMethodName, 0, pLIn, pLOut);
  625. }
  626. else
  627. break;
  628. }
  629. pOriginal->EndMethodEnumeration();
  630. }
  631. hres = 0;
  632. return hres;
  633. }
  634. //***************************************************************************
  635. //
  636. // CWbemNamespace::FixAmendedQualifiers
  637. //
  638. //***************************************************************************
  639. HRESULT CWbemNamespace::FixAmendedQualifiers(
  640. IWbemQualifierSet *pOriginal,
  641. IWbemQualifierSet *pNew
  642. )
  643. {
  644. HRESULT hres = 0;
  645. CWStringArray arrDelete;
  646. CWStringArray arrProps;
  647. BSTR strName = 0;
  648. long lFlavor;
  649. int i;
  650. pOriginal->BeginEnumeration(0);
  651. // BUGBUG EndEnum
  652. while(pOriginal->Next(0, &strName, NULL, NULL) == S_OK)
  653. {
  654. CSysFreeMe sfm(strName);
  655. if (CFlexArray::no_error != arrProps.Add(strName))
  656. return WBEM_E_OUT_OF_MEMORY;
  657. }
  658. for (i = 0; i < arrProps.Size(); i++)
  659. {
  660. _variant_t vVal;
  661. pOriginal->Get(arrProps.GetAt(i), 0, &vVal, &lFlavor);
  662. if (lFlavor & WBEM_FLAVOR_AMENDED)
  663. {
  664. // Delete the "amended" qualifier.
  665. if (CFlexArray::no_error != arrDelete.Add(arrProps.GetAt(i)))
  666. return WBEM_E_OUT_OF_MEMORY;
  667. // Restore any original qualifier value.
  668. if (pNew)
  669. {
  670. _variant_t vOldVal;
  671. long lOldFlavor;
  672. if (pNew->Get(arrProps.GetAt(i), 0, &vOldVal, &lOldFlavor) != WBEM_E_NOT_FOUND)
  673. {
  674. pOriginal->Put(arrProps.GetAt(i), &vOldVal, lOldFlavor);
  675. arrDelete.RemoveAt(arrDelete.Size()-1);
  676. }
  677. }
  678. }
  679. }
  680. pOriginal->EndEnumeration();
  681. for (i = 0; i < arrDelete.Size(); i++)
  682. {
  683. pOriginal->Delete(arrDelete.GetAt(i));
  684. }
  685. arrDelete.Empty();
  686. return hres;
  687. }
  688. //***************************************************************************
  689. //
  690. // CWbemNamespace::Exec_DeleteClass
  691. //
  692. // Actually deletes the class from the database. No class provider support.
  693. // Raises class deletion event.
  694. //
  695. // Parameters and return values are exacly the same as those for DeleteClass
  696. // as described in help
  697. //
  698. //***************************************************************************
  699. HRESULT CWbemNamespace::Exec_DeleteClass(
  700. LPWSTR pszClassName,
  701. long lFlags,
  702. IWbemContext* pCtx,
  703. CBasicObjectSink* pSink
  704. )
  705. {
  706. TIMETRACE(TimeTraces::DeleteClass);
  707. HRESULT hRes;
  708. IWbemServices *pClassProv = 0;
  709. CSynchronousSink* pSyncSink = 0;
  710. BSTR bstrClass = 0;
  711. IWbemClassObject* pStaticClassDef = 0;
  712. BOOL bInRepository = FALSE;
  713. if (pszClassName == 0 || pSink == 0)
  714. return pSink->Return(WBEM_E_INVALID_PARAMETER);
  715. if (pszClassName[0] == L'_')
  716. return pSink->Return(WBEM_E_INVALID_OPERATION);
  717. // Bring up the dynamic class provider symposium for consultation.
  718. // ===============================================================
  719. if (!m_bRepositOnly && m_pProvFact)
  720. {
  721. hRes = m_pProvFact->GetClassProvider(
  722. 0, // lFlags
  723. pCtx,
  724. m_wszUserName,
  725. m_wsLocale,
  726. m_pThisNamespace, // IWbemPath pointer
  727. 0,
  728. IID_IWbemServices,
  729. (LPVOID *) &pClassProv
  730. );
  731. if (FAILED(hRes))
  732. return pSink->Return(hRes);
  733. }
  734. CReleaseMe _2(pClassProv);
  735. _IWmiCoreWriteHook *pHook = 0;
  736. hRes = m_pCoreSvc->NewPerTaskHook(&pHook);
  737. if (FAILED(hRes))
  738. return pSink->Return(hRes);
  739. CReleaseMe _(pHook);
  740. HRESULT hHookResult = 0;
  741. // First, try repository.
  742. // ======================
  743. if (m_bRepositOnly || m_pProvFact == NULL)
  744. {
  745. if (!Allowed(WBEM_FULL_WRITE_REP))
  746. return pSink->Return(WBEM_E_ACCESS_DENIED);
  747. if (pHook)
  748. pHook->PreDelete(WBEM_FLAG_CLASS_DELETE, lFlags, pCtx, NULL,
  749. m_pThisNamespace, pszClassName );
  750. hRes = CRepository::DeleteByPath(m_pSession, m_pNsHandle, pszClassName, lFlags);
  751. if (pHook)
  752. pHook->PostDelete(WBEM_FLAG_CLASS_DELETE, hRes, pCtx, NULL, m_pThisNamespace, pszClassName, NULL);
  753. return pSink->Return(hRes);
  754. }
  755. // If here, we have to get it first because dynamic class providers
  756. // could be seriously affected by the removal of the class.
  757. // ================================================================
  758. hRes = CRepository::GetObject(
  759. m_pSession,
  760. m_pNsHandle,
  761. pszClassName,
  762. 0,
  763. &pStaticClassDef
  764. );
  765. CReleaseMe _1(pStaticClassDef);
  766. if (SUCCEEDED(hRes))
  767. {
  768. bInRepository = TRUE;
  769. if (!Allowed(WBEM_FULL_WRITE_REP))
  770. return pSink->Return(WBEM_E_ACCESS_DENIED);
  771. if (pStaticClassDef == 0)
  772. return pSink->Return(WBEM_E_CRITICAL_ERROR);
  773. }
  774. // Build up a synchronous sink to receive the class.
  775. // =================================================
  776. pSyncSink = CSynchronousSink::Create();
  777. if (pSyncSink == NULL)
  778. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  779. pSyncSink->AddRef();
  780. CReleaseMe _3(pSyncSink);
  781. // Try to get it.
  782. // ==============
  783. bstrClass = SysAllocString(pszClassName);
  784. if (bstrClass == 0)
  785. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  786. CSysFreeMe sfm(bstrClass);
  787. // If the class was in the repository, we are merely advising dynamic
  788. // class providers that the class is going away.
  789. // ==================================================================
  790. if (bInRepository)
  791. lFlags |= WBEM_FLAG_ADVISORY;
  792. else
  793. {
  794. if (!Allowed(WBEM_WRITE_PROVIDER))
  795. return pSink->Return(WBEM_E_ACCESS_DENIED);
  796. }
  797. hRes = pClassProv->DeleteClassAsync(bstrClass, lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pSyncSink);
  798. if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND)
  799. return pSink->Return(hRes);
  800. pSyncSink->Block();
  801. IWbemClassObject* pErrorObj = 0;
  802. pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
  803. CReleaseMe rmErrObj(pErrorObj);
  804. if (FAILED(hRes))
  805. {
  806. pSink->Return(hRes, pErrorObj);
  807. return hRes;
  808. }
  809. // If here, we can go ahead with it.
  810. // =================================
  811. if (pHook)
  812. pHook->PreDelete(WBEM_FLAG_CLASS_DELETE, lFlags, pCtx, NULL,
  813. m_pThisNamespace, pszClassName );
  814. if (bInRepository)
  815. hRes = CRepository::DeleteByPath(m_pSession, m_pNsHandle, pszClassName, lFlags);
  816. if (pHook)
  817. pHook->PostDelete(WBEM_FLAG_CLASS_DELETE, hRes, pCtx, NULL, m_pThisNamespace, pszClassName, NULL);
  818. return pSink->Return(hRes);
  819. }
  820. //***************************************************************************
  821. //
  822. // CWbemNamespace::Exec_CreateClassEnum
  823. //
  824. //***************************************************************************
  825. HRESULT CWbemNamespace::Exec_CreateClassEnum(
  826. LPWSTR pszSuperclass,
  827. long lFlags,
  828. IWbemContext* pCtx,
  829. CBasicObjectSink* pSink
  830. )
  831. {
  832. TIMETRACE(TimeTraces::CreateClassEnum);
  833. HRESULT hRes;
  834. IWbemClassObject* pErrorObj = 0;
  835. IWbemServices *pClassProv = 0;
  836. CSynchronousSink* pSyncSink = 0;
  837. BSTR bstrClass = 0;
  838. IWbemClassObject* pResultObj = 0;
  839. CCombiningSink* pCombiningSink = NULL;
  840. CLocaleMergingSink * pLocaleSink = NULL;
  841. CBasicObjectSink *pTmp = 0;
  842. BSTR bstrSuperclass = 0;
  843. bool bProvSSNotFound = false;
  844. bool bRepNotFound = false;
  845. // Quick check of parms.
  846. // =====================
  847. if (pSink == 0)
  848. return WBEM_E_INVALID_PARAMETER;
  849. if (pszSuperclass == 0) // Ensure we point to a blank instead of NULL with no superclass
  850. pszSuperclass = L"";
  851. else
  852. {
  853. if (illFormatedClass2 (pszSuperclass))
  854. return pSink->Return(WBEM_E_INVALID_CLASS);
  855. }
  856. // Prepare some sinks to hold everything.
  857. // ======================================
  858. if ((lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS))
  859. {
  860. pLocaleSink = new CLocaleMergingSink(pSink, m_wsLocale, m_pThisNamespace);
  861. if (pLocaleSink == NULL)
  862. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  863. pLocaleSink->AddRef();
  864. pTmp = pLocaleSink;
  865. }
  866. else
  867. pTmp = pSink;
  868. CReleaseMe _1(pLocaleSink);
  869. pCombiningSink = new CCombiningSink(pTmp);
  870. if (NULL == pCombiningSink) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  871. pCombiningSink->AddRef();
  872. CReleaseMe _2(pCombiningSink);
  873. // Bring up the dynamic class provider symposium for consultation.
  874. // ===============================================================
  875. if ( !m_bRepositOnly && m_pProvFact)
  876. {
  877. hRes = m_pProvFact->GetClassProvider(
  878. 0, // lFlags
  879. pCtx,
  880. m_wszUserName,
  881. m_wsLocale,
  882. m_pThisNamespace, // IWbemPath pointer
  883. 0,
  884. IID_IWbemServices,
  885. (LPVOID *) &pClassProv
  886. );
  887. if (FAILED(hRes))
  888. return pCombiningSink->Return(hRes);
  889. }
  890. CReleaseMe _3(pClassProv);
  891. // Get the repository classes.
  892. // ===========================
  893. BOOL bUseStatic = !(lFlags & WBEM_FLAG_NO_STATIC);
  894. if (bUseStatic)
  895. {
  896. if ((lFlags & WBEM_MASK_DEPTH) == WBEM_FLAG_DEEP)
  897. {
  898. // DEEP ENUM
  899. // ==========
  900. IWbemObjectSink *pObjSink = (IWbemObjectSink *) pCombiningSink;
  901. hRes = CRepository::QueryClasses(
  902. m_pSession,
  903. m_pNsHandle,
  904. WBEM_FLAG_DEEP | WBEM_FLAG_VALIDATE_CLASS_EXISTENCE,
  905. pszSuperclass,
  906. pObjSink);
  907. }
  908. else
  909. {
  910. // SHALLOW ENUM
  911. // =============
  912. IWbemObjectSink *pObjSink = (IWbemObjectSink *) pCombiningSink;
  913. hRes = CRepository::QueryClasses(
  914. m_pSession,
  915. m_pNsHandle,
  916. WBEM_FLAG_SHALLOW | WBEM_FLAG_VALIDATE_CLASS_EXISTENCE,
  917. pszSuperclass,
  918. pObjSink);
  919. }
  920. //If a SetStatus of INVALID_CLASS was indicated it means there is no static
  921. //class, however we need to continue on with dynamic classes, so we need
  922. //to clear the error.
  923. if ((pCombiningSink->GetHResult() == WBEM_E_NOT_FOUND) || (hRes == WBEM_E_NOT_FOUND))
  924. {
  925. bRepNotFound = true;
  926. pCombiningSink->ClearHResult();
  927. hRes = WBEM_S_NO_ERROR;
  928. }
  929. if (FAILED(hRes))
  930. {
  931. // A real failure. Give up.
  932. // =========================
  933. return pCombiningSink->Return(hRes);
  934. }
  935. }
  936. if (m_bRepositOnly || m_pProvFact == NULL)
  937. return pCombiningSink->Return(WBEM_S_NO_ERROR);
  938. // If here, we have to merge in the dynamic classes.
  939. // =================================================
  940. // Build up a synchronous sink to receive the classes.
  941. // ===================================================
  942. pSyncSink = CSynchronousSink::Create();
  943. if (pSyncSink == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  944. pSyncSink->AddRef();
  945. CReleaseMe _4(pSyncSink);
  946. // Try to get it.
  947. // ==============
  948. bstrSuperclass = SysAllocString(pszSuperclass);
  949. if (bstrSuperclass == 0)
  950. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  951. CSysFreeMe sfm99(bstrSuperclass);
  952. CDecoratingSink * pDecore = new CDecoratingSink(pSyncSink, this);
  953. if(pDecore == NULL)
  954. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  955. pDecore->AddRef();
  956. CReleaseMe cdecor(pDecore);
  957. hRes = pClassProv->CreateClassEnumAsync(bstrSuperclass, (lFlags & (~WBEM_FLAG_USE_AMENDED_QUALIFIERS)) & ~WBEM_FLAG_NO_STATIC, pCtx, pDecore);
  958. if ((pSyncSink->GetHResult() == WBEM_E_NOT_FOUND) || (hRes == WBEM_E_NOT_FOUND))
  959. {
  960. bProvSSNotFound = true;
  961. pSyncSink->ClearHResult();
  962. hRes = WBEM_S_NO_ERROR;
  963. }
  964. if (bProvSSNotFound && bRepNotFound)
  965. {
  966. //Neither the provider subsystem nor the repository found this object,
  967. //therefore we need to actually return an error!
  968. return pCombiningSink->Return(WBEM_E_INVALID_CLASS);
  969. }
  970. if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND)
  971. return pCombiningSink->Return(hRes);
  972. pSyncSink->Block();
  973. pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
  974. if (FAILED(hRes))
  975. {
  976. pCombiningSink->Return(hRes, pErrorObj);
  977. if (pErrorObj)
  978. pErrorObj->Release();
  979. return hRes;
  980. }
  981. // Otherwise, somebody claimed to have supplied some classes. Add them into to the
  982. // combining sink.
  983. // =================================================================================
  984. CRefedPointerArray<IWbemClassObject>& raObjects = pSyncSink->GetObjects();
  985. for (int i = 0; i < raObjects.GetSize(); i++)
  986. {
  987. IWbemClassObject *pClsDef = (IWbemClassObject *) raObjects[i];
  988. pCombiningSink->Indicate(1, &pClsDef);
  989. }
  990. return pCombiningSink->Return(WBEM_S_NO_ERROR);
  991. }
  992. //***************************************************************************
  993. //
  994. // CWbemNamespace::Exec_PutClass
  995. //
  996. //***************************************************************************
  997. HRESULT CWbemNamespace::Exec_PutClass(
  998. READONLY IWbemClassObject* pObj,
  999. long lFlags,
  1000. IWbemContext* pCtx,
  1001. CBasicObjectSink* pSink,
  1002. BOOL fIsInternal
  1003. )
  1004. {
  1005. TIMETRACE(TimeTraces::PutClass);
  1006. HRESULT hRes;
  1007. IWbemClassObject* pErrorObj = 0;
  1008. IWbemServices *pClassProv = 0;
  1009. CSynchronousSink* pSyncSink = 0;
  1010. BSTR bstrClass = 0;
  1011. IWbemClassObject* pStaticClassDef = 0;
  1012. BOOL bInRepository = FALSE;
  1013. // Maintains old functionality
  1014. long lRealFlags = lFlags;
  1015. if (pSink == 0)
  1016. return WBEM_E_INVALID_PARAMETER;
  1017. if (pObj == 0) return pSink->Return(WBEM_E_INVALID_PARAMETER);
  1018. // Extract the class name.
  1019. // =======================
  1020. CVARIANT v;
  1021. hRes = pObj->Get(L"__CLASS", 0, &v, 0, 0);
  1022. if (FAILED(hRes)) return pSink->Return(hRes);
  1023. WCHAR * pClassName = L"";
  1024. if (VT_BSTR == V_VT(&v) && NULL != V_BSTR(&v))
  1025. {
  1026. pClassName = V_BSTR(&v);
  1027. }
  1028. if (wcslen_max(pClassName,g_IdentifierLimit) > g_IdentifierLimit)
  1029. return pSink->Return(WBEM_E_QUOTA_VIOLATION);
  1030. COperationError OpInfo(pSink, L"PutClass",pClassName);
  1031. if (!OpInfo.IsOk()) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  1032. _IWmiObject * pIntObj = NULL;
  1033. hRes = pObj->QueryInterface(IID__IWmiObject,(void **)&pIntObj);
  1034. CReleaseMe rm1(pIntObj);
  1035. if (FAILED(hRes)) return OpInfo.ErrorOccurred(WBEM_E_INVALID_PARAMETER);
  1036. if (WBEM_S_NO_ERROR == pIntObj->IsObjectInstance())
  1037. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION);
  1038. CVARIANT v2;
  1039. hRes = pObj->Get(L"__SuperClass", 0, &v2, 0, 0);
  1040. if (FAILED(hRes))
  1041. return OpInfo.ErrorOccurred(hRes);
  1042. if (v2.GetStr() && wcslen(v2.GetStr())) // SEC:REVIEWED 2002-03-22 : OK; NULL terminator provably exists
  1043. {
  1044. if (CSystemProperties::IsIllegalDerivedClass(v2.GetStr()))
  1045. return OpInfo.ErrorOccurred(WBEM_E_INVALID_SUPERCLASS);
  1046. }
  1047. if (!fIsInternal )
  1048. {
  1049. if ((v.GetStr() == NULL) || (v.GetStr()[0] == '_')) // SEC:REVIEWED 2002-03-22 : OK; null terminator provably exists
  1050. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION);
  1051. if (v.GetStr()[wcslen(v.GetStr())-1] == '_') // SEC:REVIEWED 2002-03-22 : OK; null terminator provably exists
  1052. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
  1053. }
  1054. if ( !m_bRepositOnly && !fIsInternal && m_pProvFact )
  1055. {
  1056. // Bring up the dynamic class provider symposium for consultation.
  1057. // ===============================================================
  1058. hRes = m_pProvFact->GetClassProvider(
  1059. 0, // lFlags
  1060. pCtx,
  1061. m_wszUserName,
  1062. m_wsLocale,
  1063. m_pThisNamespace, // IWbemPath pointer
  1064. 0,
  1065. IID_IWbemServices,
  1066. (LPVOID *) &pClassProv
  1067. );
  1068. if (FAILED(hRes))
  1069. return OpInfo.ErrorOccurred(hRes);
  1070. }
  1071. CReleaseMe _2(pClassProv);
  1072. // Set up a new per-task hook.
  1073. // ===========================
  1074. _IWmiCoreWriteHook *pHook = 0;
  1075. hRes = m_pCoreSvc->NewPerTaskHook(&pHook);
  1076. if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
  1077. CReleaseMe _(pHook);
  1078. HRESULT hHookResult = 0;
  1079. // First, try repository.
  1080. // ======================
  1081. if (m_bRepositOnly || fIsInternal || m_pProvFact == NULL)
  1082. {
  1083. if (!Allowed(WBEM_FULL_WRITE_REP))
  1084. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1085. if (pHook)
  1086. pHook->PrePut(WBEM_FLAG_CLASS_PUT, lFlags, pCtx, 0,
  1087. m_pThisNamespace, v.GetStr(), (_IWmiObject *)pObj);
  1088. hRes = CRepository::PutObject(m_pSession, m_pNsHandle, IID_IWbemClassObject, pObj, lFlags);
  1089. if (pHook)
  1090. pHook->PostPut(WBEM_FLAG_CLASS_PUT, hRes, pCtx, 0, m_pThisNamespace, v.GetStr() , (_IWmiObject *)pObj, NULL);
  1091. return OpInfo.ErrorOccurred(hRes);
  1092. }
  1093. hRes = CRepository::GetObject(
  1094. m_pSession,
  1095. m_pNsHandle,
  1096. v.GetStr(),
  1097. 0,
  1098. &pStaticClassDef
  1099. );
  1100. CReleaseMe _1(pStaticClassDef);
  1101. if (SUCCEEDED(hRes))
  1102. {
  1103. bInRepository = TRUE;
  1104. if (pStaticClassDef != 0)
  1105. {
  1106. // Remove all the amended qualifiers
  1107. // =================================
  1108. if (lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS )
  1109. {
  1110. int nRes = SplitLocalized( (CWbemObject*) pObj, (CWbemObject*) pStaticClassDef );
  1111. if (FAILED(nRes))
  1112. {
  1113. return pSink->Return(nRes);
  1114. }
  1115. }
  1116. }
  1117. else
  1118. {
  1119. return OpInfo.ErrorOccurred(WBEM_E_CRITICAL_ERROR);
  1120. }
  1121. }
  1122. // Build up a synchronous sink to receive the class.
  1123. // =================================================
  1124. pSyncSink = CSynchronousSink::Create();
  1125. if (pSyncSink == NULL) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  1126. pSyncSink->AddRef();
  1127. CReleaseMe _3(pSyncSink);
  1128. // Try to put it.
  1129. // ==============
  1130. // If the class was in the repository, we are merely advising dynamic
  1131. // class providers that the class is going away.
  1132. // ==================================================================
  1133. if (bInRepository)
  1134. lFlags |= WBEM_FLAG_ADVISORY;
  1135. if (!Allowed(WBEM_WRITE_PROVIDER))
  1136. hRes = WBEM_E_ACCESS_DENIED;
  1137. else
  1138. hRes = pClassProv->PutClassAsync(pObj, lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pSyncSink);
  1139. if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND)
  1140. return OpInfo.ErrorOccurred(hRes);
  1141. pSyncSink->Block();
  1142. pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
  1143. if (SUCCEEDED(hRes)&&(!bInRepository))
  1144. {
  1145. pSink->Return(hRes, pErrorObj);
  1146. if (pErrorObj)
  1147. pErrorObj->Release();
  1148. return hRes;
  1149. }
  1150. if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND)
  1151. {
  1152. pSink->Return(hRes, pErrorObj);
  1153. if (pErrorObj)
  1154. pErrorObj->Release();
  1155. return hRes;
  1156. }
  1157. // If here, we can go ahead with it.
  1158. // =================================
  1159. if (!Allowed(WBEM_FULL_WRITE_REP))
  1160. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1161. if (pHook)
  1162. {
  1163. pHook->PrePut(WBEM_FLAG_CLASS_PUT, lFlags, pCtx, 0,
  1164. m_pThisNamespace, v.GetStr(), (_IWmiObject *)pObj);
  1165. }
  1166. hRes = CRepository::PutObject(m_pSession, m_pNsHandle, IID_IWbemClassObject, pObj, lFlags);
  1167. // Workaround for forceupdate and instances problem
  1168. if ( WBEM_E_CLASS_HAS_INSTANCES == hRes && ( lRealFlags & WBEM_FLAG_UPDATE_FORCE_MODE ) )
  1169. {
  1170. _variant_t v;
  1171. hRes = pObj->Get( L"__CLASS", 0L, &v, NULL, NULL );
  1172. if ( SUCCEEDED( hRes ) && V_VT( &v ) == VT_BSTR )
  1173. {
  1174. hRes = DeleteObject( V_BSTR( &v ), 0L, pCtx, NULL );
  1175. if ( SUCCEEDED( hRes ) )
  1176. {
  1177. hRes = CRepository::PutObject(m_pSession, m_pNsHandle, IID_IWbemClassObject, pObj, lFlags);
  1178. }
  1179. }
  1180. else
  1181. {
  1182. hRes = WBEM_E_CLASS_HAS_INSTANCES;
  1183. }
  1184. }
  1185. if (pHook)
  1186. {
  1187. pHook->PostPut(WBEM_FLAG_CLASS_PUT, hRes, pCtx, 0, m_pThisNamespace, v.GetStr() , (_IWmiObject *)pObj, NULL);
  1188. }
  1189. return OpInfo.ErrorOccurred(hRes);
  1190. }
  1191. //***************************************************************************
  1192. //
  1193. //***************************************************************************
  1194. HRESULT CWbemNamespace::Exec_CancelAsyncCall(
  1195. IWbemObjectSink* pSink
  1196. )
  1197. {
  1198. _IWmiArbitrator *pArb = CWmiArbitrator::GetUnrefedArbitrator();
  1199. HRESULT hRes = pArb->CancelTasksBySink(0, IID_IWbemObjectSink, pSink);
  1200. return hRes;
  1201. }
  1202. //***************************************************************************
  1203. //
  1204. //***************************************************************************
  1205. HRESULT CWbemNamespace::Exec_CancelProvAsyncCall(
  1206. IWbemServices* pProv, IWbemObjectSink* pSink
  1207. )
  1208. {
  1209. // Call to the actual provider
  1210. HRESULT hRes = pProv->CancelAsyncCall( pSink );
  1211. return hRes;
  1212. }
  1213. //***************************************************************************
  1214. //
  1215. // CWbemNamespace::Exec_PutInstance
  1216. //
  1217. // Actually stores the instance in the database. If the class is dynamic, the
  1218. // call is propagated to the provider.
  1219. // Raises instance creation or modification event.
  1220. //
  1221. // Parameters and return values are exacly the same as those for PutInstance
  1222. // as described in help
  1223. //
  1224. //***************************************************************************
  1225. HRESULT CWbemNamespace::Exec_PutInstance(
  1226. IWbemClassObject* pInst,
  1227. long lFlags,
  1228. IWbemContext* pCtx,
  1229. CBasicObjectSink* pSink
  1230. )
  1231. {
  1232. TIMETRACE(TimeTraces::PutInstance);
  1233. HRESULT hRes = CheckNs();
  1234. if (FAILED(hRes)) return hRes;
  1235. if (NULL == pSink) return WBEM_E_INVALID_PARAMETER;
  1236. if(pInst == NULL) return pSink->Return(WBEM_E_INVALID_PARAMETER);
  1237. COperationError OpInfo(pSink, L"PutInstance", L"");
  1238. if (!OpInfo.IsOk()) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  1239. CWbemObject *pObj = (CWbemObject *) pInst;
  1240. HRESULT hres;
  1241. _variant_t v;
  1242. hRes = pObj->Get(L"__RELPATH", 0, &v, NULL, NULL);
  1243. if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
  1244. if(VT_BSTR == V_VT(&v))
  1245. {
  1246. if (wcslen_max(V_BSTR(&v),g_PathLimit) > g_PathLimit)
  1247. return OpInfo.ErrorOccurred(WBEM_E_QUOTA_VIOLATION);
  1248. }
  1249. if (!pObj->IsInstance())
  1250. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
  1251. if (!pObj->IsKeyed())
  1252. return OpInfo.ErrorOccurred(WBEM_E_NO_KEY);
  1253. if (pObj->IsLimited())
  1254. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
  1255. if (pObj->IsClientOnly())
  1256. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
  1257. // Check if localization bits are set, and if so, that the
  1258. // AMENDED_QUALIFIERS flag was specified.
  1259. if ( ((CWbemObject*) pObj)->IsLocalized() &&
  1260. !( lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS ) )
  1261. {
  1262. return OpInfo.ErrorOccurred( WBEM_E_AMENDED_OBJECT );
  1263. }
  1264. if((lFlags & WBEM_FLAG_UPDATE_ONLY) == 0)
  1265. {
  1266. // Make sure that put extensions are not used without UPDATE_ONLY
  1267. // ==============================================================
  1268. BOOL bExtended;
  1269. hres = GetContextBoolean(pCtx, L"__PUT_EXTENSIONS", &bExtended);
  1270. if(FAILED(hres) || bExtended)
  1271. return OpInfo.ErrorOccurred(WBEM_E_INVALID_CONTEXT);
  1272. }
  1273. BSTR strPropName = NULL;
  1274. CSysFreeMeRef fmref(strPropName);
  1275. if(!pObj->ValidateRange(&strPropName))
  1276. {
  1277. OpInfo.SetParameterInfo(strPropName); // throws
  1278. return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROPERTY);
  1279. }
  1280. // Build the key string.
  1281. // =====================
  1282. CVar vClass;
  1283. hres = pObj->GetClassName(&vClass); // throw
  1284. if (FAILED(hres))
  1285. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT);
  1286. OpInfo.SetParameterInfo(vClass.GetLPWSTR()); // throws
  1287. // Get the class definition
  1288. // ========================
  1289. IWbemClassObject* pErrorObj = NULL;
  1290. IWbemClassObject* pClassObj = NULL;
  1291. hres = Exec_GetObjectByPath(vClass.GetLPWSTR(), 0, pCtx,&pClassObj, &pErrorObj);
  1292. CReleaseMe rmErrObj(pErrorObj);
  1293. CReleaseMe rm1(pClassObj);
  1294. if(hres == WBEM_E_NOT_FOUND) hres = WBEM_E_INVALID_CLASS;
  1295. if(FAILED(hres)) return OpInfo.ErrorOccurred(hres, pErrorObj);
  1296. CWbemClass *pClassDef = (CWbemClass*)pClassObj;
  1297. // Dont allow write of old security classes. This prevents
  1298. // a nefarious user from trying to slip in some extra rights
  1299. if (wbem_wcsicmp(vClass.GetLPWSTR(), L"__NTLMUser") == 0 ||
  1300. wbem_wcsicmp(vClass.GetLPWSTR(), L"__NTLMGroup") == 0)
  1301. {
  1302. if (!Allowed(WRITE_DAC))
  1303. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1304. if((lFlags & WBEM_FLAG_ONLY_STATIC) == 0)
  1305. {
  1306. return PutSecurityClassInstances(vClass.GetLPWSTR(), pInst ,
  1307. pSink, pCtx, lFlags);
  1308. }
  1309. }
  1310. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1311. // Dont allow write on the __thisnamespace instance -- except during an upgrade in setup
  1312. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1313. if (wbem_wcsicmp(vClass.GetLPWSTR(), L"__thisnamespace") == 0 && !IsNtSetupRunning())
  1314. {
  1315. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION);
  1316. }
  1317. // Make sure that the instance and the class match
  1318. // ===============================================
  1319. // SJS - Amendment is the same as Abstract
  1320. if( pClassDef->IsAmendment() || pClassDef->IsAbstract() || !pClassDef->IsKeyed() )
  1321. {
  1322. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION);
  1323. }
  1324. if(!((CWbemInstance*)pObj)->IsInstanceOf(pClassDef)) // trow
  1325. {
  1326. return OpInfo.ErrorOccurred(WBEM_E_INVALID_CLASS);
  1327. }
  1328. // Verify provider validity
  1329. // ========================
  1330. // Only administrators can change provider registration
  1331. // RAID# 566241
  1332. // ==================================
  1333. if(pObj->InheritsFrom(L"__Provider") == S_OK || pObj->InheritsFrom(L"__ProviderRegistration") == S_OK)
  1334. {
  1335. HANDLE hAccess;
  1336. hres = GetAccessToken(hAccess);
  1337. if ( FAILED (hres) )
  1338. {
  1339. if ( hres != 0x80041007 )
  1340. {
  1341. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1342. }
  1343. }
  1344. else
  1345. {
  1346. if ( !IsAdmin(hAccess))
  1347. {
  1348. CloseHandle ( hAccess );
  1349. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1350. }
  1351. CloseHandle ( hAccess );
  1352. }
  1353. }
  1354. // While the class may not be dynamically provided, some of the
  1355. // properties might be.
  1356. // ============================================================
  1357. hres = GetOrPutDynProps(pObj, PUT, pClassDef->IsDynamic());
  1358. if(FAILED(hres))
  1359. {
  1360. ERRORTRACE((LOG_WBEMCORE, "Failed to pre-process an instance of %S using "
  1361. "a property provider. Error code: %X\n",
  1362. vClass.GetLPWSTR(), hres));
  1363. }
  1364. // Recursively Put in all the right places
  1365. // ======================================
  1366. CCombiningSink* pCombSink = new CCombiningSink(OpInfo.GetSink());
  1367. if(pCombSink == NULL)
  1368. return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  1369. pCombSink->AddRef();
  1370. CReleaseMe rm2(pCombSink);
  1371. return RecursivePutInstance((CWbemInstance*)pObj, pClassDef, lFlags,
  1372. pCtx, pCombSink, TRUE);
  1373. }
  1374. //***************************************************************************
  1375. //
  1376. //***************************************************************************
  1377. HRESULT CWbemNamespace::RecursivePutInstance(
  1378. CWbemInstance* pInst,
  1379. CWbemClass* pClassDef,
  1380. long lFlags,
  1381. IWbemContext* pCtx,
  1382. CBasicObjectSink* pSink,
  1383. BOOL bLast
  1384. )
  1385. {
  1386. HRESULT hRes;
  1387. // See if any action is required at this level
  1388. // ===========================================
  1389. if (pClassDef->IsAbstract() || pClassDef->IsAmendment() || !pClassDef->IsKeyed())
  1390. return WBEM_S_FALSE;
  1391. // See if we need to go up
  1392. // =======================
  1393. BOOL bParentTookCareOfItself = TRUE;
  1394. if (pClassDef->IsDynamic())
  1395. {
  1396. // Get the parent class
  1397. // ====================
  1398. CVar vParentName;
  1399. pClassDef->GetSuperclassName(&vParentName);
  1400. if (!vParentName.IsNull())
  1401. {
  1402. IWbemClassObject* pParentClass = NULL;
  1403. IWbemClassObject* pErrorObj = NULL;
  1404. hRes = Exec_GetObjectByPath(vParentName.GetLPWSTR(), 0, pCtx,&pParentClass, &pErrorObj);
  1405. CReleaseMe rm1(pParentClass);
  1406. CReleaseMe rm2(pErrorObj);
  1407. if (FAILED(hRes))
  1408. {
  1409. pSink->Return(hRes, pErrorObj);
  1410. return hRes;
  1411. }
  1412. // Get it to put it's portion
  1413. // ==========================
  1414. hRes = RecursivePutInstance(pInst, (CWbemClass*)pParentClass,lFlags, pCtx, pSink, FALSE);
  1415. if(FAILED(hRes))
  1416. return hRes;
  1417. if(hRes == WBEM_S_FALSE)
  1418. bParentTookCareOfItself = FALSE;
  1419. }
  1420. }
  1421. // Parent Puts have been taken care of. Call it on our own class.
  1422. // ==============================================================
  1423. // Convert the instance to the right class
  1424. // =======================================
  1425. CWbemInstance* pNewInst = NULL;
  1426. pInst->ConvertToClass(pClassDef, &pNewInst);
  1427. CReleaseMe rm1((IWbemClassObject*)pNewInst);
  1428. if (pNewInst == NULL)
  1429. {
  1430. ERRORTRACE((LOG_WBEMCORE, "Failed to convert an instance to a base class\n"));
  1431. return pSink->Return(WBEM_E_CRITICAL_ERROR);
  1432. }
  1433. if (pClassDef->IsDynamic())
  1434. {
  1435. // Check if we need to do a put at this level
  1436. // ==========================================
  1437. if (!bLast && (lFlags & WBEM_FLAG_UPDATE_ONLY))
  1438. {
  1439. hRes = IsPutRequiredForClass(pClassDef, pInst, pCtx, bParentTookCareOfItself);
  1440. if (FAILED(hRes))
  1441. return pSink->Return(hRes);
  1442. if (hRes == WBEM_S_FALSE)
  1443. {
  1444. // No need to put this class
  1445. // =========================
  1446. return pSink->Return(WBEM_S_NO_ERROR);
  1447. }
  1448. }
  1449. // Get the provider name.
  1450. // ======================
  1451. CVar vProv;
  1452. hRes = pClassDef->GetQualifier(L"Provider", &vProv);
  1453. if (FAILED(hRes) || vProv.GetType() != VT_BSTR)
  1454. {
  1455. return pSink->Return(WBEM_E_INVALID_PROVIDER_REGISTRATION);
  1456. }
  1457. // Access the provider cache. First check permission
  1458. // ==================================================
  1459. if (!Allowed(WBEM_WRITE_PROVIDER))
  1460. return pSink->Return(WBEM_E_ACCESS_DENIED);
  1461. CSynchronousSink* pSyncSink = CSynchronousSink::Create(pSink);
  1462. if(pSyncSink == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  1463. pSyncSink->AddRef();
  1464. CReleaseMe rmSync(pSyncSink);
  1465. IWbemServices *pProv = 0;
  1466. if(m_pProvFact == NULL) return pSink->Return(WBEM_E_CRITICAL_ERROR);
  1467. WmiInternalContext t_InternalContext ;
  1468. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
  1469. hRes = m_pProvFact->GetProvider(
  1470. t_InternalContext ,
  1471. 0, // lFlags
  1472. pCtx,
  1473. 0,
  1474. m_wszUserName,
  1475. m_wsLocale,
  1476. 0, // IWbemPath pointer
  1477. vProv, // Provider
  1478. IID_IWbemServices,
  1479. (LPVOID *) &pProv
  1480. );
  1481. if (FAILED(hRes)) return pSink->Return(hRes);
  1482. CReleaseMe _(pProv);
  1483. pProv->PutInstanceAsync(pNewInst, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pSyncSink);
  1484. pSyncSink->Block();
  1485. IWbemClassObject* pErrorObj = NULL;
  1486. BSTR str;
  1487. pSyncSink->GetStatus(&hRes, &str, &pErrorObj);
  1488. CSysFreeMe sfm(str);
  1489. CReleaseMe rmErrObj(pErrorObj);
  1490. rmSync.release();
  1491. // It is ok if the upper levels report "provider not capable".
  1492. // ===========================================================
  1493. if (!bLast && hRes == WBEM_E_PROVIDER_NOT_CAPABLE)
  1494. hRes = 0;
  1495. if (FAILED(hRes))
  1496. {
  1497. COperationError OpInfo(pSink, L"PutInstance", L"");
  1498. if (!OpInfo.IsOk()) return WBEM_E_OUT_OF_MEMORY;
  1499. OpInfo.ProviderReturned(vProv.GetLPWSTR(), hRes, pErrorObj);
  1500. return hRes;
  1501. }
  1502. else if (str)
  1503. {
  1504. pSink->SetStatus(0, hRes, str, NULL);
  1505. }
  1506. // Provider passes back NULL, we should construct the instance path and return to client
  1507. // NT RAID: 186286 [marioh]
  1508. // ======================================================================================
  1509. else
  1510. {
  1511. BSTR str = NULL;
  1512. LPWSTR wszPath = pNewInst->GetRelPath();
  1513. if (wszPath )
  1514. {
  1515. str = SysAllocString(wszPath);
  1516. delete [] wszPath;
  1517. }
  1518. pSink->SetStatus(0, hRes, str, NULL);
  1519. SysFreeString(str);
  1520. }
  1521. return WBEM_S_NO_ERROR;
  1522. }
  1523. // The class is not dynamically provided.
  1524. // ======================================
  1525. hRes = ((CWbemInstance*)pNewInst)->PlugKeyHoles();
  1526. if (FAILED(hRes))
  1527. return pSink->Return(hRes);
  1528. // Get the path.
  1529. // =============
  1530. CVar vClass;
  1531. hRes = pNewInst->GetClassName(&vClass);
  1532. if (FAILED(hRes))
  1533. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  1534. WCHAR * ClassNameStr = vClass.GetLPWSTR();
  1535. // Check permissions for writes on system classes.
  1536. // ===============================================
  1537. bool derivedFromSys = false;
  1538. HRESULT hr = IsDerivedFromSystem(*pNewInst, &derivedFromSys);
  1539. if (FAILED(hr)) return pSink->Return(hr);
  1540. if (derivedFromSys)
  1541. {
  1542. if (!Allowed(WBEM_FULL_WRITE_REP))
  1543. return pSink->Return(WBEM_E_ACCESS_DENIED);
  1544. }
  1545. else if (!Allowed(WBEM_PARTIAL_WRITE_REP))
  1546. {
  1547. return pSink->Return(WBEM_E_ACCESS_DENIED);
  1548. }
  1549. CVARIANT v;
  1550. hRes = pNewInst->Get(L"__RELPATH", 0, &v, 0, 0);
  1551. if(FAILED(hRes))
  1552. return pSink->Return(hRes);
  1553. if(v.GetType() != VT_BSTR)
  1554. return pSink->Return(WBEM_E_CRITICAL_ERROR);
  1555. // Set up a new per-task hook.
  1556. // ===========================
  1557. _IWmiCoreWriteHook *pHook = 0;
  1558. hRes = m_pCoreSvc->NewPerTaskHook(&pHook);
  1559. if (FAILED(hRes))
  1560. return pSink->Return(hRes);
  1561. CReleaseMe _(pHook);
  1562. HRESULT hHookResult = 0;
  1563. // See if the instance already exists.
  1564. // ===================================
  1565. IWbemClassObject *pExistingObject = 0;
  1566. hRes = CRepository::GetObject(m_pSession, m_pScopeHandle, v.GetStr(),0, &pExistingObject);
  1567. CReleaseMe _2(pExistingObject);
  1568. if (FAILED(hRes))
  1569. {
  1570. // If we here, we failed to get it from the repository. Thus, it needs to be created from scratch.
  1571. // ================================================================================================
  1572. // Remove all the amended qualifiers
  1573. // =================================
  1574. if (lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS )
  1575. {
  1576. int nRes = SplitLocalized(pNewInst);
  1577. if (FAILED(nRes))
  1578. return pSink->Return(nRes);
  1579. }
  1580. if((lFlags & WBEM_MASK_CREATE_UPDATE) == WBEM_FLAG_UPDATE_ONLY)
  1581. {
  1582. return pSink->Return(WBEM_E_NOT_FOUND);
  1583. }
  1584. // As a special case, see if the object is
  1585. // of class <__NAMESPACE>. If so, create a new namespace
  1586. // for it.
  1587. // ======================================================
  1588. if ((wbem_wcsicmp(vClass.GetLPWSTR(), L"__NAMESPACE") == 0) ||
  1589. (CRepository::InheritsFrom(m_pSession, m_pNsHandle, L"__NAMESPACE", vClass.GetLPWSTR()) == 0))
  1590. {
  1591. hRes = CreateNamespace(pNewInst);
  1592. if (FAILED(hRes))
  1593. return pSink->Return(hRes);
  1594. }
  1595. // Not a __NAMESPACE or derivative.
  1596. // ================================
  1597. else
  1598. {
  1599. // If here, the object didn't already exist in the repository, so we
  1600. // can add it to the database.
  1601. // ==================================================================
  1602. // Check if this instance makes any sense to
  1603. // hook callbacks.
  1604. // =========================================
  1605. hRes = DecorateObject(pNewInst);
  1606. if (FAILED(hRes))
  1607. return pSink->Return(hRes);
  1608. IWbemClassObject* pInstObj = pNewInst;
  1609. IWbemClassObject* pOldObj = 0;
  1610. if (pHook)
  1611. {
  1612. // If there are hooks, try them and note whether callback is required.
  1613. // ===================================================================
  1614. hHookResult = pHook->PrePut(WBEM_FLAG_INST_PUT, lFlags, pCtx, 0,
  1615. m_pThisNamespace, ClassNameStr, pNewInst
  1616. );
  1617. }
  1618. if (FAILED(hHookResult))
  1619. {
  1620. return pSink->Return(hHookResult);
  1621. }
  1622. if (hHookResult == WBEM_S_POSTHOOK_WITH_BOTH)
  1623. {
  1624. CRepository::GetObject(m_pSession, m_pNsHandle, v.GetStr(), 0, &pOldObj);
  1625. }
  1626. // Actually create it in the database
  1627. // ==================================
  1628. hRes = CRepository::PutObject(m_pSession, m_pScopeHandle, IID_IWbemClassObject, LPVOID(pNewInst), DWORD(lFlags));
  1629. if (pHook)
  1630. pHook->PostPut(WBEM_FLAG_INST_PUT, hRes, pCtx, 0, m_pThisNamespace, ClassNameStr, pNewInst, (_IWmiObject *) pOldObj);
  1631. delete pOldObj;
  1632. if (FAILED(hRes))
  1633. {
  1634. return pSink->Return(hRes);
  1635. }
  1636. }
  1637. }
  1638. // If here, the object was already in the repository and requires updating.
  1639. // ========================================================================
  1640. else
  1641. {
  1642. if((lFlags & WBEM_MASK_CREATE_UPDATE) == WBEM_FLAG_CREATE_ONLY)
  1643. {
  1644. return pSink->Return(WBEM_E_ALREADY_EXISTS);
  1645. }
  1646. // Remove all the amended qualifiers
  1647. // =================================
  1648. if (lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS )
  1649. {
  1650. int nRes = SplitLocalized(pNewInst, (CWbemObject *) pExistingObject);
  1651. if (FAILED(nRes))
  1652. {
  1653. return pSink->Return(nRes);
  1654. }
  1655. }
  1656. // Check if this update makes any sense to the ESS
  1657. // ===============================================
  1658. hRes = DecorateObject(pNewInst);
  1659. if (FAILED(hRes))
  1660. return pSink->Return(hRes);
  1661. IWbemClassObject* pInstObj = pNewInst;
  1662. // Check pre-hook.
  1663. // ===============
  1664. if (pHook)
  1665. {
  1666. // If there are hooks, try them and note whether callback is required.
  1667. // ===================================================================
  1668. hHookResult = pHook->PrePut(WBEM_FLAG_INST_PUT, lFlags, pCtx, 0,
  1669. m_pThisNamespace, ClassNameStr, pNewInst
  1670. );
  1671. }
  1672. if (FAILED(hHookResult))
  1673. return pSink->Return(hHookResult);
  1674. // Actually create it in the database
  1675. // ==================================
  1676. hRes = CRepository::PutObject(m_pSession, m_pScopeHandle, IID_IWbemClassObject, LPVOID(pNewInst), DWORD(lFlags));
  1677. // Post put.
  1678. // =========
  1679. if (pHook)
  1680. pHook->PostPut(WBEM_FLAG_INST_PUT, hRes, pCtx, 0, m_pThisNamespace, ClassNameStr, pNewInst, (_IWmiObject *) pExistingObject);
  1681. if (FAILED(hRes))
  1682. return pSink->Return(hRes);
  1683. }
  1684. // Assign appropriate value to the path
  1685. // ====================================
  1686. LPWSTR wszPath = pNewInst->GetRelPath();
  1687. BSTR str = SysAllocString(wszPath);
  1688. delete [] wszPath;
  1689. pSink->SetStatus(0, WBEM_S_NO_ERROR, str, NULL);
  1690. SysFreeString(str);
  1691. return WBEM_NO_ERROR;
  1692. }
  1693. //***************************************************************************
  1694. //
  1695. //***************************************************************************
  1696. HRESULT CWbemNamespace::CreateNamespace(CWbemInstance *pNewInst)
  1697. {
  1698. //
  1699. // internal interface throws
  1700. //
  1701. CVar vNsName;
  1702. HRESULT hRes = pNewInst->GetProperty(L"Name", &vNsName);
  1703. if (FAILED(hRes) || vNsName.IsNull())
  1704. {
  1705. return WBEM_E_INVALID_NAMESPACE;
  1706. }
  1707. // verify that this name is valid
  1708. // ==============================
  1709. if (!IsValidElementName(vNsName.GetLPWSTR(),g_PathLimit-NAMESPACE_ADJUSTMENT))
  1710. {
  1711. return WBEM_E_INVALID_NAMESPACE;
  1712. }
  1713. if (!Allowed(WBEM_FULL_WRITE_REP))
  1714. {
  1715. return WBEM_E_ACCESS_DENIED;
  1716. }
  1717. //Get a new session for transactioning purposes...
  1718. IWmiDbSession *pSession = NULL;
  1719. IWmiDbSessionEx *pSessionEx = NULL;
  1720. hRes = CRepository::GetNewSession(&pSession);
  1721. if (FAILED(hRes))
  1722. return hRes;
  1723. //Get an EX version that supports transactioning...
  1724. pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pSessionEx);
  1725. if (pSessionEx)
  1726. {
  1727. pSession->Release();
  1728. pSession = pSessionEx;
  1729. }
  1730. CReleaseMe relMe1(pSession);
  1731. //If we have transactionable session, use it!
  1732. if (pSessionEx)
  1733. {
  1734. hRes = pSessionEx->BeginWriteTransaction(0);
  1735. if (FAILED(hRes))
  1736. {
  1737. return hRes;
  1738. }
  1739. }
  1740. try
  1741. {
  1742. // Build the new namespace name.
  1743. // =============================
  1744. // Create the namespace
  1745. // =====================
  1746. if (SUCCEEDED(hRes))
  1747. hRes = CRepository::PutObject(pSession, m_pScopeHandle, IID_IWbemClassObject, LPVOID(pNewInst), 0);
  1748. // Set the default instances.
  1749. // ===============================
  1750. CWbemNamespace* pNewNs = NULL;
  1751. if (SUCCEEDED(hRes))
  1752. pNewNs = CWbemNamespace::CreateInstance();
  1753. if (SUCCEEDED(hRes) && pNewNs != NULL)
  1754. {
  1755. int iLen = 2;
  1756. if(m_pThisNamespace)
  1757. iLen += wcslen(m_pThisNamespace); // SEC:REVIEWED 2002-03-22 : OK; null terminator is there by prior precondition
  1758. if(vNsName.GetLPWSTR())
  1759. iLen += wcslen(vNsName.GetLPWSTR()); // SEC:REVIEWED 2002-03-22 : OK; provably ok or we couldn't be here
  1760. WCHAR * pTemp = new WCHAR[iLen];
  1761. if(pTemp)
  1762. {
  1763. *pTemp = L'\0';
  1764. if(m_pThisNamespace)
  1765. {
  1766. StringCchCopyW(pTemp, iLen, m_pThisNamespace);
  1767. StringCchCatW(pTemp, iLen, L"\\");
  1768. }
  1769. if(vNsName.GetLPWSTR())
  1770. StringCchCatW(pTemp, iLen, vNsName.GetLPWSTR());
  1771. //Initialize the namespace object
  1772. hRes = pNewNs->Initialize(pTemp,GetUserName(), 0, 0, FALSE, TRUE, // SEC:REVIEWED 2002-03-22 : OK
  1773. NULL, 0xFFFFFFFF, TRUE, pSession);
  1774. delete pTemp;
  1775. }
  1776. else
  1777. {
  1778. hRes = WBEM_E_OUT_OF_MEMORY;
  1779. }
  1780. if(SUCCEEDED(hRes))
  1781. {
  1782. hRes = CRepository::EnsureNsSystemInstances(pSession, pNewNs->m_pNsHandle, pSession, m_pNsHandle);
  1783. }
  1784. if (SUCCEEDED(hRes))
  1785. hRes = InitializeSD(pSession);
  1786. pNewNs->Release();
  1787. }
  1788. else if (SUCCEEDED(hRes))
  1789. {
  1790. hRes = WBEM_E_OUT_OF_MEMORY;
  1791. }
  1792. }
  1793. catch (CX_MemoryException &)
  1794. {
  1795. hRes = WBEM_E_OUT_OF_MEMORY;
  1796. }
  1797. catch (...)
  1798. {
  1799. ExceptionCounter c;
  1800. ERRORTRACE((LOG_WBEMCORE, "Namespace Creation of <%S> caused a very critical error!\n", vNsName.GetLPWSTR()));
  1801. hRes = WBEM_E_CRITICAL_ERROR;
  1802. }
  1803. if (FAILED(hRes))
  1804. {
  1805. ERRORTRACE((LOG_WBEMCORE, "Namespace Creation of <%S> caused an error <0x%X>!\n", vNsName.GetLPWSTR(), hRes));
  1806. if (pSessionEx)
  1807. pSessionEx->AbortTransaction(0);
  1808. }
  1809. else
  1810. {
  1811. hRes = DecorateObject(pNewInst);
  1812. if (FAILED(hRes))
  1813. {
  1814. if (pSessionEx)
  1815. pSessionEx->AbortTransaction(0);
  1816. }
  1817. else
  1818. {
  1819. if (pSessionEx)
  1820. {
  1821. hRes = pSessionEx->CommitTransaction(0);
  1822. }
  1823. }
  1824. }
  1825. return hRes;
  1826. }
  1827. //***************************************************************************
  1828. //
  1829. // CWbemNamespace::Exec_DeleteInstance
  1830. //
  1831. // Actually deletes the instance from the database. No instance provider
  1832. // support. Raises instance deletion event.
  1833. //
  1834. // Parameters and return values are exacly the same as those for DeleteInstance
  1835. // as described in help
  1836. //
  1837. //***************************************************************************
  1838. HRESULT CWbemNamespace::Exec_DeleteInstance(
  1839. READONLY LPWSTR wszObjectPath,
  1840. long lFlags,
  1841. IWbemContext* pCtx,
  1842. CBasicObjectSink* pSink
  1843. )
  1844. {
  1845. TIMETRACE(TimeTraces::DeleteInstance);
  1846. return DeleteSingleInstance(wszObjectPath, lFlags, pCtx, pSink);
  1847. }
  1848. //***************************************************************************
  1849. //
  1850. //***************************************************************************
  1851. //
  1852. HRESULT CWbemNamespace::DeleteSingleInstance(
  1853. READONLY LPWSTR wszObjectPath,
  1854. long lFlags,
  1855. IWbemContext* pCtx,
  1856. CBasicObjectSink* pSink
  1857. )
  1858. {
  1859. HRESULT hRes;
  1860. int nRes;
  1861. COperationError OpInfo(pSink, L"DeleteInstance", wszObjectPath);
  1862. if ( !OpInfo.IsOk() ) return WBEM_E_OUT_OF_MEMORY;
  1863. // Parse the object path to get the class involved.
  1864. // ================================================
  1865. ParsedObjectPath* pOutput = 0;
  1866. CObjectPathParser p;
  1867. int nStatus = p.Parse(wszObjectPath, &pOutput);
  1868. OnDeleteObj<ParsedObjectPath*,CObjectPathParser,
  1869. void (CObjectPathParser:: *)(ParsedObjectPath *pOutput),
  1870. &CObjectPathParser::Free> FreeMe(&p,pOutput);
  1871. if (nStatus != 0 || !pOutput->IsInstance())
  1872. {
  1873. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
  1874. }
  1875. // Exception for __WinMgmtIdentification
  1876. if (!wbem_wcsicmp(pOutput->m_pClass, L"__CIMOMIdentification") ||
  1877. !wbem_wcsicmp(pOutput->m_pClass, L"__SystemSecurity") ||
  1878. !wbem_wcsicmp(pOutput->m_pClass, L"__ADAPStatus" ) )
  1879. {
  1880. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION);
  1881. }
  1882. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1883. // Dont allow deletion on the __thisnamespace instance
  1884. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1885. if (wbem_wcsicmp(pOutput->m_pClass, L"__thisnamespace") == 0 )
  1886. {
  1887. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OPERATION);
  1888. }
  1889. // Special case for the old security classes
  1890. // ==========================================
  1891. if (wbem_wcsicmp(pOutput->m_pClass, L"__NTLMUser") == 0 ||
  1892. wbem_wcsicmp(pOutput->m_pClass, L"__NTLMGroup") == 0)
  1893. {
  1894. if (!Allowed(WRITE_DAC))
  1895. {
  1896. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1897. }
  1898. if((lFlags & WBEM_FLAG_ONLY_STATIC) == 0)
  1899. {
  1900. return DeleteSecurityClassInstances(pOutput, pSink, pCtx,lFlags);
  1901. }
  1902. }
  1903. // As a special case, see if the object is
  1904. // of class <__NAMESPACE>. If so, (TEMP) disallow deletion.
  1905. // =========================================================
  1906. WString wsNamespaceName;
  1907. if (wbem_wcsicmp(pOutput->m_pClass, L"__NAMESPACE") == 0 ||
  1908. CRepository::InheritsFrom(m_pSession, m_pScopeHandle, L"__NAMESPACE", pOutput->m_pClass) == 0
  1909. )
  1910. {
  1911. if (!Allowed(WBEM_FULL_WRITE_REP))
  1912. {
  1913. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1914. }
  1915. if (pOutput->m_dwNumKeys != 1)
  1916. {
  1917. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
  1918. }
  1919. KeyRef* pKey = pOutput->m_paKeys[0];
  1920. if (pKey->m_pName != NULL && wbem_wcsicmp(pKey->m_pName, L"name"))
  1921. {
  1922. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
  1923. }
  1924. if (V_VT(&pKey->m_vValue) != VT_BSTR)
  1925. {
  1926. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
  1927. }
  1928. // Prevent deletion of standard namespaces.
  1929. // ========================================
  1930. if (wbem_wcsicmp(m_pThisNamespace, L"ROOT") == 0)
  1931. {
  1932. BSTR pNs = V_BSTR(&pKey->m_vValue);
  1933. if (!pNs)
  1934. {
  1935. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
  1936. }
  1937. if (wbem_wcsicmp(pNs, L"SECURITY") == 0)
  1938. {
  1939. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1940. }
  1941. if (wbem_wcsicmp(pNs, L"DEFAULT") == 0)
  1942. {
  1943. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  1944. }
  1945. }
  1946. // Set up hook.
  1947. // ============
  1948. _IWmiCoreWriteHook *pHook = 0;
  1949. HRESULT hRes = m_pCoreSvc->NewPerTaskHook(&pHook);
  1950. CReleaseMe _(pHook);
  1951. HRESULT hHookResult = 0;
  1952. LPWSTR pszClassName = 0;
  1953. IWbemPath *pPath = 0;
  1954. CVectorDeleteMe<WCHAR> vdmClassName(&pszClassName);
  1955. if (pHook)
  1956. {
  1957. // Parse the object path.
  1958. // ======================
  1959. hRes = m_pCoreSvc->CreatePathParser(0, &pPath);
  1960. if (FAILED(hRes))
  1961. {
  1962. return OpInfo.ErrorOccurred(hRes);
  1963. }
  1964. CReleaseMe _3Path(pPath);
  1965. hRes = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, wszObjectPath);
  1966. if (FAILED(hRes))
  1967. {
  1968. return OpInfo.ErrorOccurred(hRes);
  1969. }
  1970. ULONG uBuf = 0;
  1971. hRes = pPath->GetClassName(&uBuf, 0);
  1972. if (FAILED(hRes))
  1973. {
  1974. return OpInfo.ErrorOccurred(hRes);
  1975. }
  1976. pszClassName = new wchar_t[uBuf+1];
  1977. if (pszClassName == 0)
  1978. {
  1979. return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  1980. }
  1981. hRes = pPath->GetClassName(&uBuf, pszClassName);
  1982. if (FAILED(hRes))
  1983. {
  1984. return OpInfo.ErrorOccurred(hRes);
  1985. }
  1986. // If there are hooks, try them and note whether callback is required.
  1987. // ===================================================================
  1988. hHookResult = pHook->PreDelete(WBEM_FLAG_INST_DELETE, lFlags, pCtx, pPath,
  1989. m_pThisNamespace, pszClassName);
  1990. if (FAILED(hHookResult))
  1991. {
  1992. return OpInfo.ErrorOccurred(hHookResult);
  1993. }
  1994. pPath->AddRef();
  1995. }
  1996. CReleaseMe _2Path(pPath);
  1997. // Ensure the object can be reached so that we can delete it.
  1998. // ==========================================================
  1999. IWbemClassObject *pExistingObject = 0;
  2000. hRes = CRepository::GetObject(m_pSession, m_pScopeHandle, wszObjectPath, 0, &pExistingObject);
  2001. if (FAILED(hRes))
  2002. {
  2003. return OpInfo.ErrorOccurred(hRes);
  2004. }
  2005. CReleaseMe _2(pExistingObject);
  2006. if (hRes == WBEM_S_NO_ERROR) // new test
  2007. {
  2008. // Check if we may
  2009. // ===============
  2010. if (!Allowed(WBEM_FULL_WRITE_REP))
  2011. {
  2012. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  2013. }
  2014. // Go ahead and try the deletion.
  2015. // ==============================
  2016. WString sNamespace = "__Namespace='";
  2017. sNamespace += V_BSTR(&pKey->m_vValue);
  2018. sNamespace += "'";
  2019. hRes = CRepository::DeleteByPath(m_pSession, m_pScopeHandle, LPWSTR(sNamespace), 0);
  2020. // Call post hook.
  2021. // ===============
  2022. if (pHook)
  2023. pHook->PostDelete(WBEM_FLAG_INST_DELETE, hRes, pCtx, pPath,
  2024. m_pThisNamespace, pszClassName, (_IWmiObject *) pExistingObject);
  2025. // Decide what to do if things didn't work out.
  2026. // ============================================
  2027. if (FAILED(hRes))
  2028. {
  2029. return OpInfo.ErrorOccurred(hRes);
  2030. }
  2031. }
  2032. else
  2033. {
  2034. return OpInfo.ErrorOccurred(hRes);
  2035. }
  2036. wsNamespaceName = V_BSTR(&pKey->m_vValue);
  2037. return OpInfo.ErrorOccurred(WBEM_S_NO_ERROR);
  2038. }
  2039. // See if the class is dynamic
  2040. // ===========================
  2041. CWbemObject *pClassDef = 0;
  2042. IWbemClassObject* pErrorObj = NULL;
  2043. IWbemClassObject* pClassObj = NULL;
  2044. HRESULT hres = Exec_GetObjectByPath(pOutput->m_pClass, 0,
  2045. pCtx,&pClassObj, &pErrorObj);
  2046. CReleaseMe rmErrObj(pErrorObj);
  2047. CReleaseMe rmClsDef(pClassObj);
  2048. if(hres == WBEM_E_NOT_FOUND) hres = WBEM_E_INVALID_CLASS;
  2049. if(FAILED(hres))
  2050. {
  2051. OpInfo.ErrorOccurred(hres, pErrorObj);
  2052. return WBEM_S_NO_ERROR;
  2053. }
  2054. pClassDef = (CWbemObject*)pClassObj;
  2055. CVar vDynFlag;
  2056. hres = pClassDef->GetQualifier(L"Dynamic", &vDynFlag);
  2057. if (SUCCEEDED(hres) && vDynFlag.GetType() == VT_BOOL && vDynFlag.GetBool())
  2058. {
  2059. // Get the provider name.
  2060. CVar vProv;
  2061. hres = pClassDef->GetQualifier(L"Provider", &vProv);
  2062. if (FAILED(hres) || vProv.GetType() != VT_BSTR)
  2063. {
  2064. return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION);
  2065. }
  2066. if (!Allowed(WBEM_WRITE_PROVIDER))
  2067. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  2068. // Access the provider cache.
  2069. // ==========================
  2070. IWbemServices *pProv = 0;
  2071. HRESULT hRes;
  2072. if(m_pProvFact == NULL)
  2073. return OpInfo.ErrorOccurred(WBEM_E_CRITICAL_ERROR);
  2074. WmiInternalContext t_InternalContext ;
  2075. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) );
  2076. hRes = m_pProvFact->GetProvider(t_InternalContext ,
  2077. 0, // lFlags
  2078. pCtx,
  2079. 0,
  2080. m_wszUserName,
  2081. m_wsLocale,
  2082. 0, // IWbemPath pointer
  2083. vProv, // Provider
  2084. IID_IWbemServices,
  2085. (LPVOID *) &pProv);
  2086. if (FAILED(hRes))
  2087. {
  2088. return OpInfo.ErrorOccurred(hRes);
  2089. }
  2090. CReleaseMe rmProv(pProv);
  2091. hRes = pProv->DeleteInstanceAsync( wszObjectPath,
  2092. lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  2093. pCtx,
  2094. OpInfo.GetSink());
  2095. return WBEM_S_NO_ERROR;
  2096. }
  2097. // The class is not dynamically provided.
  2098. // ======================================
  2099. // Only administrators can change provider registration
  2100. // RAID# 566241
  2101. // ==================================
  2102. if(pClassDef->InheritsFrom(L"__Provider") == S_OK || pClassDef->InheritsFrom(L"__ProviderRegistration") == S_OK)
  2103. {
  2104. HANDLE hAccess;
  2105. hres = GetAccessToken (hAccess);
  2106. if ( FAILED (hres) )
  2107. {
  2108. if ( hres != 0x80041007 )
  2109. {
  2110. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  2111. }
  2112. }
  2113. else
  2114. {
  2115. if ( !IsAdmin(hAccess))
  2116. {
  2117. CloseHandle ( hAccess );
  2118. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  2119. }
  2120. CloseHandle ( hAccess );
  2121. }
  2122. }
  2123. bool derivedFromSys = false;
  2124. HRESULT hr = IsDerivedFromSystem(*pClassDef, &derivedFromSys);
  2125. if (FAILED(hr)) return pSink->Return(hr);
  2126. if (derivedFromSys)
  2127. {
  2128. if (!Allowed(WBEM_FULL_WRITE_REP))
  2129. return pSink->Return(WBEM_E_ACCESS_DENIED);
  2130. }
  2131. else if (!Allowed(WBEM_PARTIAL_WRITE_REP))
  2132. {
  2133. return pSink->Return(WBEM_E_ACCESS_DENIED);
  2134. }
  2135. rmClsDef.release();
  2136. // If here, it is a normal object. First retrieve
  2137. // the object for the event subsystem, then go ahead and delete it.
  2138. // ================================================================
  2139. // Prehook.
  2140. // ========
  2141. _IWmiCoreWriteHook *pHook = 0;
  2142. hRes = m_pCoreSvc->NewPerTaskHook(&pHook);
  2143. if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
  2144. CReleaseMe rmHook(pHook);
  2145. HRESULT hHookResult = 0;
  2146. LPWSTR pszClassName = 0;
  2147. IWbemPath *pPath = 0;
  2148. CReleaseMeRef<IWbemPath*> rmPath(pPath);
  2149. CVectorDeleteMe<WCHAR> vdmClassName(&pszClassName);
  2150. if (pHook)
  2151. {
  2152. // Parse the object path.
  2153. hRes = m_pCoreSvc->CreatePathParser(0, &pPath);
  2154. if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
  2155. hRes = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, wszObjectPath);
  2156. if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
  2157. ULONG uBuf = 0;
  2158. hRes = pPath->GetClassName(&uBuf, 0);
  2159. if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
  2160. pszClassName = new wchar_t[uBuf+1];
  2161. if (pszClassName == 0) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  2162. hRes = pPath->GetClassName(&uBuf, pszClassName);
  2163. if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
  2164. // If there are hooks, try them and note whether callback is required.
  2165. // ===================================================================
  2166. hHookResult = pHook->PreDelete(WBEM_FLAG_INST_DELETE, lFlags, pCtx, pPath,m_pThisNamespace, pszClassName);
  2167. if (FAILED(hHookResult)) return OpInfo.ErrorOccurred(hHookResult);
  2168. }
  2169. // If anybody wants to see the old object, get it.
  2170. IWbemClassObject *pDoomedInstance = NULL ;
  2171. if (hHookResult == WBEM_S_POSTHOOK_WITH_OLD)
  2172. {
  2173. hRes = CRepository::GetObject(m_pSession, m_pScopeHandle, wszObjectPath,0, &pDoomedInstance);
  2174. if (FAILED(hRes)) return OpInfo.ErrorOccurred(hRes);
  2175. }
  2176. CReleaseMe _Doomed (pDoomedInstance) ;
  2177. hRes = CRepository::DeleteByPath(m_pSession, m_pScopeHandle, wszObjectPath, 0); // new
  2178. // Posthook.
  2179. if (pHook)
  2180. pHook->PostDelete(WBEM_FLAG_INST_DELETE, hRes, pCtx, pPath,
  2181. m_pThisNamespace, pszClassName, (_IWmiObject *) pDoomedInstance);
  2182. if ( FAILED (hRes) ) return OpInfo.ErrorOccurred(hRes);
  2183. return OpInfo.ErrorOccurred(WBEM_NO_ERROR);
  2184. }
  2185. //***************************************************************************
  2186. //
  2187. // CWbemNamespace::Exec_CreateInstanceEnum
  2188. //
  2189. // Actually creates the enumerator for all instances of a given class,
  2190. // optionally recursively. Interacts with instance providers. Class provider
  2191. // interaction works, but is sparsely tested.
  2192. //
  2193. // Parameters and return values are exacly the same as those for
  2194. // CreateInstanceEnum as described in help
  2195. //
  2196. //***************************************************************************
  2197. HRESULT CWbemNamespace::Exec_CreateInstanceEnum(
  2198. LPWSTR wszClass,
  2199. long lFlags,
  2200. IWbemContext* pCtx,
  2201. CBasicObjectSink* pSink
  2202. )
  2203. {
  2204. TIMETRACE(TimeTraces::CreateInstanceEnum);
  2205. COperationError OpInfo(pSink, L"CreateInstanceEnum", wszClass);
  2206. if ( !OpInfo.IsOk() ) return WBEM_E_OUT_OF_MEMORY;
  2207. // Make sure the name of the class is a name
  2208. // =========================================
  2209. if(wcschr(wszClass, L':'))
  2210. return OpInfo.ErrorOccurred(WBEM_E_INVALID_CLASS);
  2211. // Create equivalent query
  2212. // =======================
  2213. WString wsQuery;
  2214. wsQuery += L"select * from ";
  2215. wsQuery += wszClass;
  2216. if((lFlags & WBEM_MASK_DEPTH) == WBEM_FLAG_SHALLOW)
  2217. {
  2218. wsQuery += L" where __CLASS = \"";
  2219. wsQuery += wszClass;
  2220. wsQuery += L"\"";
  2221. }
  2222. CErrorChangingSink* pErrSink = new CErrorChangingSink(OpInfo.GetSink(),WBEM_E_INVALID_QUERY, WBEM_E_INVALID_CLASS);
  2223. if(pErrSink == NULL) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  2224. CReleaseMe rmErrorChange(pErrSink);
  2225. // Execute it
  2226. CQueryEngine::ExecQuery(this,L"WQL",(LPWSTR)wsQuery,lFlags,pCtx,pErrSink);
  2227. return WBEM_S_NO_ERROR;
  2228. }
  2229. //***************************************************************************
  2230. //
  2231. //***************************************************************************
  2232. /*
  2233. void CWbemNamespace::SetUserName(LPWSTR wName)
  2234. {
  2235. try
  2236. {
  2237. delete m_wszUserName;
  2238. m_wszUserName = (wName) ? Macro_CloneLPWSTR(wName):NULL;
  2239. }
  2240. catch(...)
  2241. {
  2242. ExceptionCounter c;
  2243. m_wszUserName = 0;
  2244. }
  2245. }
  2246. */
  2247. //***************************************************************************
  2248. //
  2249. //***************************************************************************
  2250. HRESULT CWbemNamespace::GetObjectByFullPath(
  2251. READONLY LPWSTR wszObjectPath,
  2252. IWbemPath * pOutput,
  2253. long lFlags,
  2254. IWbemContext* pCtx,
  2255. CBasicObjectSink* pSink
  2256. )
  2257. {
  2258. // Get the namespace part of the path
  2259. DWORD dwSizeNamespace = 0;
  2260. HRESULT hres = pOutput->GetText(WBEMPATH_GET_NAMESPACE_ONLY, &dwSizeNamespace, NULL);
  2261. if(FAILED(hres))
  2262. return hres;
  2263. LPWSTR wszNewNamespace = new WCHAR[dwSizeNamespace];
  2264. if(wszNewNamespace == NULL)
  2265. return WBEM_E_OUT_OF_MEMORY;
  2266. CDeleteMe<WCHAR> dm1(wszNewNamespace);
  2267. hres = pOutput->GetText(WBEMPATH_GET_NAMESPACE_ONLY, &dwSizeNamespace, wszNewNamespace);
  2268. if(FAILED(hres))
  2269. return hres;
  2270. // Get the relative part of the path
  2271. DWORD dwSizeRelative = 0;
  2272. hres = pOutput->GetText(WBEMPATH_GET_RELATIVE_ONLY, &dwSizeRelative, NULL);
  2273. if(FAILED(hres))
  2274. return hres;
  2275. LPWSTR wszRelativePath = new WCHAR[dwSizeRelative];
  2276. if(wszRelativePath == NULL)
  2277. return WBEM_E_OUT_OF_MEMORY;
  2278. CDeleteMe<WCHAR> dm2(wszRelativePath);
  2279. hres = pOutput->GetText(WBEMPATH_GET_RELATIVE_ONLY, &dwSizeRelative, wszRelativePath);
  2280. if(FAILED(hres))
  2281. return hres;
  2282. if (pOutput->IsLocal(ConfigMgr::GetMachineName()))
  2283. {
  2284. // In win2k, we allowed \\.\root\default:whatever, but not root\default:whatever
  2285. // So, the following additional test was added
  2286. ULONGLONG uFlags;
  2287. hres = pOutput->GetInfo(0, &uFlags);
  2288. if(SUCCEEDED(hres))
  2289. {
  2290. if((uFlags & WBEMPATH_INFO_PATH_HAD_SERVER) == 0)
  2291. return pSink->Return(WBEM_E_INVALID_OBJECT_PATH);
  2292. }
  2293. bool bAlreadyAuthenticated = (m_dwSecurityFlags & SecFlagWin9XLocal) != 0;
  2294. CWbemNamespace* pNewLocal = CWbemNamespace::CreateInstance();
  2295. if(pNewLocal == NULL)
  2296. return WBEM_E_OUT_OF_MEMORY;
  2297. hres = pNewLocal->Initialize(wszNewNamespace, m_wszUserName,
  2298. (bAlreadyAuthenticated) ? m_dwSecurityFlags : 0,
  2299. (bAlreadyAuthenticated) ? m_dwPermission : 0,
  2300. m_bForClient, false,
  2301. m_pszClientMachineName,
  2302. m_dwClientProcessID,
  2303. FALSE,NULL);
  2304. if (FAILED(hres))
  2305. {
  2306. pNewLocal->Release();
  2307. return hres;
  2308. }
  2309. else if (pNewLocal->GetStatus())
  2310. {
  2311. hres = pNewLocal->GetStatus();
  2312. pNewLocal->Release();
  2313. return hres;
  2314. }
  2315. // check for security if this isnt the local 9x case
  2316. if(!bAlreadyAuthenticated)
  2317. {
  2318. DWORD dwAccess = pNewLocal->GetUserAccess();
  2319. if((dwAccess & WBEM_ENABLE) == 0)
  2320. {
  2321. delete pNewLocal;
  2322. return WBEM_E_ACCESS_DENIED;
  2323. }
  2324. else
  2325. pNewLocal->SetPermissions(dwAccess);
  2326. }
  2327. if(pNewLocal->GetStatus())
  2328. {
  2329. hres = pNewLocal->GetStatus();
  2330. delete pNewLocal;
  2331. return pSink->Return(hres);
  2332. }
  2333. #if 0
  2334. pNewLocal->AddRef();
  2335. #endif
  2336. pNewLocal->SetLocale(GetLocale());
  2337. hres = pNewLocal->Exec_GetObject(wszRelativePath,
  2338. lFlags, pCtx, pSink);
  2339. pNewLocal->Release();
  2340. return hres;
  2341. }
  2342. else
  2343. {
  2344. // Disable remote retrieval for V1
  2345. // ===============================
  2346. return pSink->Return(WBEM_E_NOT_SUPPORTED);
  2347. }
  2348. }
  2349. //***************************************************************************
  2350. //
  2351. // CWbemNamespace::Exec_GetObjectByPath
  2352. //
  2353. // Actually retrieves an object (a class or an instance) from the database.
  2354. // Interacts properly with class and instance providers and uses property
  2355. // providers for post-processing (See GetOrPutDynProps).
  2356. //
  2357. // Parameters and return values are exacly the same as those for GetObject
  2358. // as described in help
  2359. //
  2360. //***************************************************************************
  2361. HRESULT CWbemNamespace::Exec_GetObjectByPath(
  2362. READONLY LPWSTR wszObjectPath,
  2363. long lFlags,
  2364. IWbemContext* pCtx,
  2365. NEWOBJECT IWbemClassObject** ppObj,
  2366. NEWOBJECT IWbemClassObject** ppErrorObj
  2367. )
  2368. {
  2369. TIMETRACE(TimeTraces::GetObjectByPath);
  2370. HRESULT hres = WBEM_S_NO_ERROR;
  2371. CSynchronousSink* pSyncSink = CSynchronousSink::Create();
  2372. if(pSyncSink == NULL)
  2373. return WBEM_E_OUT_OF_MEMORY;
  2374. pSyncSink->AddRef();
  2375. IWbemClassObject* pErrorObj = NULL;
  2376. IWbemClassObject* pObj = NULL;
  2377. hres = Exec_GetObject(wszObjectPath, lFlags, pCtx, pSyncSink);
  2378. if (SUCCEEDED(hres))
  2379. {
  2380. pSyncSink->Block();
  2381. pSyncSink->GetStatus(&hres, NULL, &pErrorObj);
  2382. if(SUCCEEDED(hres))
  2383. {
  2384. if(pSyncSink->GetObjects().GetSize() < 1)
  2385. {
  2386. pSyncSink->Release();
  2387. ERRORTRACE((LOG_WBEMCORE, "Sync sink returned success with no objects!\n"));
  2388. return WBEM_E_CRITICAL_ERROR;
  2389. }
  2390. pObj = pSyncSink->GetObjects()[0];
  2391. pObj->AddRef();
  2392. }
  2393. }
  2394. pSyncSink->Release();
  2395. if(ppObj) *ppObj = pObj;
  2396. else if(pObj) pObj->Release();
  2397. if(ppErrorObj) *ppErrorObj = pErrorObj;
  2398. else if(pErrorObj) pErrorObj->Release();
  2399. return hres;
  2400. }
  2401. //***************************************************************************
  2402. //
  2403. //***************************************************************************
  2404. HRESULT CWbemNamespace::Exec_GetObject(
  2405. READONLY LPWSTR wszObjectPath,
  2406. long lFlags,
  2407. IWbemContext* pCtx,
  2408. CBasicObjectSink* pSink)
  2409. {
  2410. TIMETRACE(TimeTraces::GetObject);
  2411. // Create a sink that will merge the localized qualifiers
  2412. // over the top of the default qualifiers (if specified)
  2413. // ======================================================
  2414. CLocaleMergingSink *pLocaleSink = NULL;
  2415. HRESULT hres = WBEM_S_NO_ERROR;
  2416. if (wszObjectPath && wszObjectPath[0] && wszObjectPath[0] != L'_') // SEC:REVIEWED 2002-03-22 : OK; prior testing ensures that this is valid
  2417. {
  2418. if ((lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS))
  2419. {
  2420. pLocaleSink = new CLocaleMergingSink(pSink, m_wsLocale, m_pThisNamespace);
  2421. if(pLocaleSink == NULL)
  2422. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  2423. else
  2424. {
  2425. pLocaleSink->AddRef();
  2426. pSink = pLocaleSink;
  2427. }
  2428. }
  2429. }
  2430. CReleaseMe rm(pLocaleSink);
  2431. COperationError OpInfo(pSink, L"GetObject", wszObjectPath?wszObjectPath:L"");
  2432. if (!OpInfo.IsOk()) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  2433. // Check if the path is NULL --- that's valid
  2434. // ==========================================
  2435. if (wszObjectPath == NULL || wszObjectPath[0] == 0) // SEC:REVIEWED 2002-03-22 : OK; null terminator provably exists
  2436. {
  2437. //
  2438. // BUGBUG consider using CoCreateInstance instead of new CWbemClass
  2439. //
  2440. CWbemClass * pNewObj = new CWbemClass;
  2441. if(NULL == pNewObj) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  2442. CReleaseMe rm_((IWbemClassObject*)pNewObj);
  2443. hres = pNewObj->InitEmpty(0);
  2444. if (FAILED(hres)) return OpInfo.ErrorOccurred(hres);
  2445. IWbemClassObject* pObj = pNewObj;
  2446. pSink->Indicate(1, &pObj);
  2447. return OpInfo.ErrorOccurred(WBEM_NO_ERROR);
  2448. }
  2449. // here we are sure the path is not null
  2450. if (wcslen_max(wszObjectPath,g_PathLimit) > g_PathLimit)
  2451. return OpInfo.ErrorOccurred(WBEM_E_QUOTA_VIOLATION);
  2452. // Parse the object path to get the class involved.
  2453. // ================================================
  2454. IWbemPath *pPath = ConfigMgr::GetNewPath();
  2455. if (pPath == 0)
  2456. {
  2457. return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  2458. }
  2459. CReleaseMe _1(pPath);
  2460. hres = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, wszObjectPath);
  2461. if (FAILED(hres))
  2462. {
  2463. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
  2464. }
  2465. ULONGLONG uResponse;
  2466. hres = pPath->GetInfo(0, &uResponse);
  2467. if (FAILED(hres) || (
  2468. (uResponse & WBEMPATH_INFO_IS_INST_REF) == 0 &&
  2469. (uResponse & WBEMPATH_INFO_IS_CLASS_REF) == 0))
  2470. {
  2471. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
  2472. }
  2473. if (!pPath->IsRelative(ConfigMgr::GetMachineName(), m_pThisNamespace))
  2474. {
  2475. // This path points to another namespace. Delegate to it instead
  2476. // =============================================================
  2477. hres = GetObjectByFullPath(wszObjectPath, pPath,
  2478. lFlags, pCtx, OpInfo.GetSink());
  2479. return OpInfo.ErrorOccurred(hres);
  2480. }
  2481. BOOL bInstance = (uResponse & WBEMPATH_INFO_IS_INST_REF);
  2482. // The repository code can't handle paths like root\default:classname
  2483. // So if there is a colon, pass a pointer to one past it
  2484. WCHAR * pRelativePath = wszObjectPath;
  2485. for(WCHAR * pTest = wszObjectPath;*pTest;pTest++)
  2486. {
  2487. if(*pTest == L':')
  2488. {
  2489. // In win2k, we allowed \\.\root\default:whatever, but not root\default:whatever
  2490. // So, the following additional test was added
  2491. if((uResponse & WBEMPATH_INFO_PATH_HAD_SERVER) == 0)
  2492. return OpInfo.ErrorOccurred(WBEM_E_INVALID_OBJECT_PATH);
  2493. pRelativePath = pTest+1;
  2494. break;
  2495. }
  2496. else if (*pTest==L'=')
  2497. break; //got to key part...
  2498. }
  2499. if (bInstance)
  2500. {
  2501. CFinalizingSink* pFinalSink = new CFinalizingSink(this, OpInfo.GetSink());
  2502. if(pFinalSink == NULL) return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  2503. pFinalSink->AddRef();
  2504. CReleaseMe rmFinal(pFinalSink);
  2505. hres = Exec_GetInstance(pRelativePath, pPath, lFlags, pCtx, pFinalSink);
  2506. if (FAILED(hres)) return OpInfo.ErrorOccurred(hres);
  2507. }
  2508. else
  2509. {
  2510. hres = Exec_GetClass(pRelativePath, lFlags, pCtx, OpInfo.GetSink());
  2511. if (FAILED(hres)) return OpInfo.ErrorOccurred(hres);
  2512. }
  2513. return hres;
  2514. }
  2515. //***************************************************************************
  2516. //
  2517. //***************************************************************************
  2518. HRESULT CWbemNamespace::Exec_GetInstance(LPCWSTR wszObjectPath,
  2519. IWbemPath* pParsedPath, long lFlags, IWbemContext* pCtx,
  2520. CBasicObjectSink* pSink)
  2521. {
  2522. if (pParsedPath->IsSameClassName(L"__NTLMUser") ||
  2523. pParsedPath->IsSameClassName(L"__NTLMGroup"))
  2524. {
  2525. if((lFlags & WBEM_FLAG_ONLY_STATIC) == 0)
  2526. {
  2527. ParsedObjectPath* pOutput = 0; // todo, convert to use new parser
  2528. CObjectPathParser p;
  2529. int nStatus = p.Parse(wszObjectPath, &pOutput);
  2530. if (nStatus != 0)
  2531. {
  2532. p.Free(pOutput);
  2533. return WBEM_E_INVALID_OBJECT_PATH;
  2534. }
  2535. HRESULT hr = GetSecurityClassInstances(pOutput, pSink, pCtx,lFlags);
  2536. p.Free(pOutput);
  2537. return hr;
  2538. }
  2539. }
  2540. // Try static database first
  2541. // =========================
  2542. if((lFlags & WBEM_FLAG_NO_STATIC) == 0)
  2543. {
  2544. IWbemClassObject *pObj = 0;
  2545. HRESULT hRes = CRepository::GetObject(m_pSession, m_pScopeHandle, wszObjectPath, lFlags, &pObj);
  2546. if (SUCCEEDED(hRes))
  2547. {
  2548. hRes = WBEM_S_NO_ERROR;
  2549. pSink->Add(pObj);
  2550. pObj->Release();
  2551. return pSink->Return(hRes);
  2552. }
  2553. }
  2554. // Try dynamic
  2555. // ===========
  2556. return DynAux_GetInstance((LPWSTR)wszObjectPath, lFlags, pCtx, pSink);
  2557. }
  2558. //***************************************************************************
  2559. //
  2560. //***************************************************************************
  2561. HRESULT CWbemNamespace::Exec_GetClass(
  2562. LPCWSTR pszClassName,
  2563. long lFlags,
  2564. IWbemContext* pCtx,
  2565. CBasicObjectSink* pSink
  2566. )
  2567. {
  2568. HRESULT hRes = 0;
  2569. IWbemClassObject* pErrorObj = 0;
  2570. IWbemServices *pClassProv = 0;
  2571. CSynchronousSink* pSyncSink = 0;
  2572. BSTR bstrClass = 0;
  2573. IWbemClassObject* pResultObj = 0;
  2574. if (pszClassName == 0 || pSink == 0)
  2575. return pSink->Return(WBEM_E_INVALID_PARAMETER);
  2576. if (!m_bRepositOnly && m_pProvFact)
  2577. {
  2578. hRes = m_pProvFact->GetClassProvider(
  2579. 0, // lFlags
  2580. pCtx,
  2581. m_wszUserName,
  2582. m_wsLocale,
  2583. m_pThisNamespace, // IWbemPath pointer
  2584. 0,
  2585. IID_IWbemServices,
  2586. (LPVOID *) &pClassProv
  2587. );
  2588. if (FAILED(hRes))
  2589. return pSink->Return(hRes);
  2590. }
  2591. CReleaseMe _1(pClassProv);
  2592. // First, try repository. If it's there, end of story.
  2593. // ====================================================
  2594. if ((lFlags & WBEM_FLAG_NO_STATIC) == 0)
  2595. {
  2596. if (m_pNsHandle)
  2597. {
  2598. hRes = CRepository::GetObject(
  2599. m_pSession,
  2600. m_pNsHandle,
  2601. pszClassName,
  2602. 0,
  2603. &pResultObj
  2604. );
  2605. }
  2606. else // Something drastically wrong
  2607. {
  2608. hRes = WBEM_E_CRITICAL_ERROR;
  2609. return pSink->Return(hRes);
  2610. }
  2611. if (SUCCEEDED(hRes) && pResultObj)
  2612. {
  2613. pSink->Add(pResultObj);
  2614. pResultObj->Release();
  2615. return pSink->Return(hRes);
  2616. }
  2617. }
  2618. // If we are in repository-only mode, we don't bother
  2619. // with dynamic classes.
  2620. // ===================================================
  2621. if (m_bRepositOnly || m_pProvFact == NULL)
  2622. return pSink->Return(WBEM_E_NOT_FOUND);
  2623. // If here, try the dynamic class providers.
  2624. // =========================================
  2625. // Build up a synchronous sink to receive the class.
  2626. // =================================================
  2627. pSyncSink = CSynchronousSink::Create();
  2628. if (pSyncSink == NULL)
  2629. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  2630. pSyncSink->AddRef();
  2631. CReleaseMe _2(pSyncSink);
  2632. // Try to get it.
  2633. // ==============
  2634. bstrClass = SysAllocString(pszClassName);
  2635. if (bstrClass == 0) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  2636. CSysFreeMe sfm(bstrClass);
  2637. {
  2638. CDecoratingSink * pDecore = new CDecoratingSink(pSyncSink, this);
  2639. if(pDecore == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  2640. pDecore->AddRef();
  2641. CReleaseMe rmDecor(pDecore);
  2642. hRes = pClassProv->GetObjectAsync(bstrClass, lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pDecore);
  2643. }
  2644. if (FAILED(hRes))
  2645. return pSink->Return(hRes);
  2646. pSyncSink->Block();
  2647. pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
  2648. if (FAILED(hRes))
  2649. {
  2650. pSink->Return(hRes, pErrorObj);
  2651. if (pErrorObj)
  2652. pErrorObj->Release();
  2653. return hRes;
  2654. }
  2655. // Otherwise, somebody claimed to have supplied it. Do we really believe them? No choice.
  2656. // =======================================================================================
  2657. if(pSyncSink->GetObjects().GetSize() < 1)
  2658. {
  2659. ERRORTRACE((LOG_WBEMCORE, "Sync sink returned success with no objects!\n"));
  2660. return pSink->Return(WBEM_E_CRITICAL_ERROR);
  2661. }
  2662. pResultObj = pSyncSink->GetObjects()[0];
  2663. pSink->Add(pResultObj);
  2664. pSink->Return(WBEM_S_NO_ERROR);
  2665. return hRes;
  2666. }
  2667. //***************************************************************************
  2668. //
  2669. //***************************************************************************
  2670. // ok
  2671. HRESULT CWbemNamespace::ExecNotificationQuery(
  2672. const BSTR QueryLanguage,
  2673. const BSTR Query,
  2674. long lFlags,
  2675. IWbemContext* pCtx,
  2676. IEnumWbemClassObject** ppEnum
  2677. )
  2678. {
  2679. try
  2680. {
  2681. HRESULT hRes = CheckNs();
  2682. if (FAILED(hRes))
  2683. return hRes;
  2684. DEBUGTRACE((LOG_WBEMCORE,
  2685. "CALL CWbemNamespace::ExecNotificationQuery\n"
  2686. " BSTR QueryLanguage = %S\n"
  2687. " BSTR Query = %S\n"
  2688. " lFlags = 0x%X\n"
  2689. " IEnumWbemClassObject **pEnum = 0x%X\n",
  2690. QueryLanguage,
  2691. Query,
  2692. lFlags,
  2693. ppEnum
  2694. ));
  2695. // Validate parameters
  2696. // ===================
  2697. if (ppEnum == NULL)
  2698. return WBEM_E_INVALID_PARAMETER;
  2699. *ppEnum = NULL;
  2700. if ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) == 0)
  2701. return WBEM_E_INVALID_PARAMETER;
  2702. if ((lFlags & WBEM_FLAG_FORWARD_ONLY) == 0)
  2703. return WBEM_E_INVALID_PARAMETER;
  2704. if (lFlags
  2705. & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS
  2706. & ~WBEM_RETURN_IMMEDIATELY
  2707. & ~WBEM_FLAG_FORWARD_ONLY
  2708. #ifdef _WBEM_WHISTLER_UNCUT
  2709. & ~WBEM_FLAG_MONITOR
  2710. #endif
  2711. )
  2712. return WBEM_E_INVALID_PARAMETER;
  2713. // Create Finalizer.
  2714. // =================
  2715. _IWmiFinalizer *pFnz = 0;
  2716. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  2717. if (FAILED(hRes))
  2718. return hRes;
  2719. CReleaseMe _1(pFnz);
  2720. ULONG uTaskType = WMICORE_TASK_EXEC_NOTIFICATION_QUERY;
  2721. if (lFlags & WBEM_RETURN_IMMEDIATELY)
  2722. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  2723. else
  2724. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  2725. // Do the work.
  2726. // ============
  2727. hRes = _ExecNotificationQueryAsync(uTaskType, pFnz, 0, QueryLanguage, Query,
  2728. lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY,
  2729. pCtx, NULL);
  2730. if (FAILED(hRes))
  2731. {
  2732. return hRes;
  2733. }
  2734. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  2735. pFnz->GetOperationResult(0, INFINITE, &hRes);
  2736. if (SUCCEEDED(hRes))
  2737. {
  2738. IEnumWbemClassObject* pEnum = NULL;
  2739. hRes = pFnz->GetResultObject(lFlags, IID_IEnumWbemClassObject, (LPVOID*)&pEnum);
  2740. if (FAILED(hRes))
  2741. return hRes;
  2742. CReleaseMe _2(pEnum);
  2743. if (SUCCEEDED(hRes))
  2744. {
  2745. *ppEnum = pEnum;
  2746. pEnum->AddRef(); // Counteract CReleaseMe
  2747. }
  2748. }
  2749. return hRes;
  2750. }
  2751. catch(...)
  2752. {
  2753. ExceptionCounter c;
  2754. return WBEM_E_CRITICAL_ERROR;
  2755. }
  2756. }
  2757. //
  2758. //
  2759. // this function can throw or return
  2760. //
  2761. //////////////////////////////////////////////////////////
  2762. HRESULT CWbemNamespace::_ExecNotificationQueryAsync(
  2763. IN ULONG uInternalFlags,
  2764. IN _IWmiFinalizer *pFnz,
  2765. IN _IWmiCoreHandle *phTask,
  2766. IN const BSTR strQueryLanguage,
  2767. IN const BSTR strQuery,
  2768. IN long lFlags,
  2769. IN IWbemContext __RPC_FAR *pCtx,
  2770. IN IWbemObjectSink __RPC_FAR *pHandler
  2771. )
  2772. {
  2773. HRESULT hRes = CheckNs();
  2774. if (FAILED(hRes))
  2775. return hRes;
  2776. if (!Allowed(WBEM_ENABLE))
  2777. return WBEM_E_ACCESS_DENIED;
  2778. DEBUGTRACE((LOG_WBEMCORE,
  2779. "CALL CWbemNamespace::_ExecNotificationQueryAsync\n"
  2780. " BSTR QueryLanguage = %S\n"
  2781. " BSTR Query = %S\n"
  2782. " lFlags = 0x%X\n"
  2783. " IWbemObjectSink* pHandler = 0x%X\n",
  2784. strQueryLanguage,
  2785. strQuery,
  2786. lFlags,
  2787. pHandler));
  2788. // Parameter validation.
  2789. // =====================
  2790. if (pFnz == 0 && pHandler == 0)
  2791. return WBEM_E_INVALID_PARAMETER;
  2792. if (strQueryLanguage == 0 || strQuery == 0 || strQueryLanguage[0] == 0)
  2793. return WBEM_E_INVALID_PARAMETER;
  2794. if (strQuery[0] == 0 )
  2795. return WBEM_E_UNPARSABLE_QUERY;
  2796. if (wcslen_max(strQuery,g_QueryLimit) > g_QueryLimit) return WBEM_E_QUOTA_VIOLATION;
  2797. if (lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS )
  2798. return WBEM_E_INVALID_PARAMETER;
  2799. m_bForClient=FALSE; // Forces a cheap fast-track
  2800. // Create Finalizer.
  2801. // =================
  2802. IWbemObjectSink *pPseudoSink = 0;
  2803. if (pFnz == 0)
  2804. {
  2805. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  2806. if (FAILED(hRes))
  2807. return hRes;
  2808. }
  2809. else // borrowed finalizer
  2810. {
  2811. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  2812. if (FAILED(hRes))
  2813. return hRes;
  2814. pFnz->AddRef();
  2815. }
  2816. CReleaseMe _1(pPseudoSink);
  2817. CReleaseMe _2(pFnz);
  2818. // Add the request to the queue.
  2819. // =============================
  2820. IWbemEventSubsystem_m4* pEss = ConfigMgr::GetEssSink();
  2821. CReleaseMe _3(pEss);
  2822. if (pEss == 0)
  2823. {
  2824. return WBEM_E_NOT_SUPPORTED; // ESS must be disabled
  2825. }
  2826. HANDLE hEssValidate = CreateEvent(NULL,FALSE,FALSE,NULL);
  2827. if (NULL == hEssValidate) return WBEM_E_OUT_OF_MEMORY;
  2828. CCloseMe cm(hEssValidate);
  2829. HRESULT hResEssCheck = 0;
  2830. wmilib::auto_ptr<CAsyncReq_ExecNotificationQueryAsync> pReq;
  2831. pReq.reset(new CAsyncReq_ExecNotificationQueryAsync(this, pEss, strQueryLanguage,
  2832. strQuery, lFlags, pPseudoSink, pCtx,
  2833. &hResEssCheck, hEssValidate));
  2834. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  2835. if ( NULL == pReq->GetContext() ) return WBEM_E_OUT_OF_MEMORY;
  2836. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  2837. if (FAILED(hRes)) return hRes;
  2838. _1.release();
  2839. // Enqueue the request.
  2840. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  2841. if (FAILED(hRes))
  2842. {
  2843. pFnz->CancelTask (0);
  2844. return hRes;
  2845. }
  2846. pReq.release(); // queue took ownership
  2847. // In this case, we have to wait long enough for ESS to accept the task.
  2848. WaitForSingleObject(hEssValidate, INFINITE);
  2849. // If ESS failed, we should cancel the task
  2850. // ========================================
  2851. if ( FAILED (hResEssCheck) )
  2852. {
  2853. pFnz->CancelTask(0);
  2854. }
  2855. return hResEssCheck;
  2856. }
  2857. //***************************************************************************
  2858. //
  2859. //***************************************************************************
  2860. // done
  2861. HRESULT CWbemNamespace::ExecNotificationQueryAsync(
  2862. IN const BSTR strQueryLanguage,
  2863. IN const BSTR strQuery,
  2864. IN long lFlags,
  2865. IN IWbemContext __RPC_FAR *pCtx,
  2866. IN IWbemObjectSink __RPC_FAR *pHandler
  2867. )
  2868. {
  2869. try
  2870. {
  2871. return _ExecNotificationQueryAsync(WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_EXEC_NOTIFICATION_QUERY,
  2872. 0, 0,
  2873. strQueryLanguage, strQuery, lFlags, pCtx, pHandler);
  2874. }
  2875. catch (...)
  2876. {
  2877. ExceptionCounter c;
  2878. return WBEM_E_CRITICAL_ERROR;
  2879. }
  2880. }
  2881. //***************************************************************************
  2882. //
  2883. //***************************************************************************
  2884. //
  2885. HRESULT CWbemNamespace::GetImplementationClass(
  2886. IWbemClassObject * pTestClass,
  2887. LPWSTR wszMethodName,
  2888. IWbemContext* pCtx,
  2889. IWbemClassObject ** ppClassObj
  2890. )
  2891. {
  2892. try
  2893. {
  2894. // If the method is disabled, or implemented in this class, we are done!
  2895. // =====================================================================
  2896. CVar Var;
  2897. CWbemClass * pClassDef = (CWbemClass *)pTestClass;
  2898. HRESULT hres = pClassDef->GetMethodQualifier(wszMethodName, L"DISABLED", &Var);
  2899. if(hres == S_OK && Var.GetBool() == VARIANT_TRUE)
  2900. return WBEM_E_METHOD_DISABLED;
  2901. hres = pClassDef->GetMethodQualifier(wszMethodName, L"IMPLEMENTED", &Var);
  2902. if(hres == S_OK && Var.GetBool() == VARIANT_TRUE)
  2903. {
  2904. // The test class is correct, return it
  2905. pTestClass->AddRef();
  2906. *ppClassObj = pTestClass;
  2907. return S_OK;
  2908. }
  2909. // Not done, get the name of the parent class.
  2910. SCODE hRes = pClassDef->GetSystemPropertyByName(L"__superclass", &Var);
  2911. if(hRes != S_OK)
  2912. return WBEM_E_CRITICAL_ERROR;
  2913. if(Var.GetType() != VT_BSTR)
  2914. return WBEM_E_METHOD_NOT_IMPLEMENTED; // no superclass --- no implementation
  2915. BSTR bstrParent = Var.GetBSTR();
  2916. if(bstrParent == NULL)
  2917. return WBEM_E_CRITICAL_ERROR; // NULL, but not VT_NULL
  2918. if(wcslen(bstrParent) < 1)
  2919. {
  2920. SysFreeString(bstrParent);
  2921. return WBEM_E_FAILED; // empty parent name????
  2922. }
  2923. IWbemClassObject * pParent = NULL;
  2924. hres = Exec_GetObjectByPath(bstrParent, 0, pCtx, &pParent, NULL);
  2925. SysFreeString(bstrParent);
  2926. if(FAILED(hres))
  2927. return WBEM_E_FAILED; // class provider failure or weird interaction
  2928. hRes = GetImplementationClass(pParent, wszMethodName, pCtx, ppClassObj);
  2929. pParent->Release();
  2930. return hRes;
  2931. }
  2932. catch(CX_Exception &)
  2933. {
  2934. return WBEM_E_FAILED;
  2935. }
  2936. }
  2937. //***************************************************************************
  2938. //
  2939. // CWbemNamespace::Exec_ExecMethod
  2940. //
  2941. // Executes a method. If the method is not tagged by the [bypass_getobject]
  2942. // qualifier, the method is passed directly to the method provider. Otherwise,
  2943. // a GetObject call is done first to ensure the instance is valid.
  2944. //
  2945. //***************************************************************************
  2946. //
  2947. HRESULT CWbemNamespace::Exec_ExecMethod(
  2948. LPWSTR wszObjectPath,
  2949. LPWSTR wszMethodName,
  2950. long lFlags,
  2951. IWbemClassObject *pInParams,
  2952. IWbemContext *pCtx,
  2953. CBasicObjectSink* pSink
  2954. )
  2955. {
  2956. TIMETRACE(TimeTraces::ExecMethod);
  2957. // Lotsa useful variables.
  2958. // =======================
  2959. HRESULT hRes;
  2960. IWbemClassObject* pClassDef = NULL;
  2961. IWbemClassObject* pImplementationClass = NULL;
  2962. IWbemPath *pPath = 0;
  2963. IWbemQualifierSet *pQSet = 0;
  2964. IWbemClassObject* pErrorObj = NULL;
  2965. BOOL bPathIsToClassObject = FALSE;
  2966. LPWSTR pszClassName = 0;
  2967. ULONGLONG uInf = 0;
  2968. // Set up a sink error object and check it.
  2969. COperationError OpInfo(pSink, L"ExecMethod", wszObjectPath);
  2970. if ( !OpInfo.IsOk() ) return WBEM_E_OUT_OF_MEMORY;
  2971. // Parse the path to the object.
  2972. // =============================
  2973. // Backwards compatibility - parsing a NULL path returns WBEM_E_INVALID_OBJECT_PATH
  2974. if ( NULL == wszObjectPath || NULL == *wszObjectPath )
  2975. {
  2976. return OpInfo.ErrorOccurred( WBEM_E_INVALID_METHOD );
  2977. }
  2978. hRes = m_pCoreSvc->CreatePathParser(0, &pPath);
  2979. if (FAILED(hRes))
  2980. return OpInfo.ErrorOccurred(hRes);
  2981. CReleaseMe _1(pPath);
  2982. hRes = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, wszObjectPath);
  2983. if (FAILED(hRes))
  2984. return OpInfo.ErrorOccurred(hRes);
  2985. ULONG uBuf = 0;
  2986. hRes = pPath->GetClassName(&uBuf, 0); // Discover the buffer size
  2987. if (FAILED(hRes))
  2988. return OpInfo.ErrorOccurred(hRes);
  2989. pszClassName = new wchar_t[uBuf+1]; // Allocate a buffer for the class name
  2990. if (pszClassName == 0)
  2991. return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  2992. wmilib::auto_buffer <wchar_t> _2(pszClassName); // Auto-delete buffer
  2993. hRes = pPath->GetClassName(&uBuf, pszClassName); // Get class name
  2994. if (FAILED(hRes))
  2995. return OpInfo.ErrorOccurred(hRes);
  2996. // Find out if a path to an instance or a class.
  2997. // ==============================================
  2998. hRes = pPath->GetInfo(0, &uInf);
  2999. if (FAILED(hRes))
  3000. return OpInfo.ErrorOccurred(hRes);
  3001. if (uInf & WBEMPATH_INFO_IS_INST_REF)
  3002. bPathIsToClassObject = FALSE;
  3003. else
  3004. bPathIsToClassObject = TRUE;
  3005. // Get the class definition. We'll need it whether or not we validate the
  3006. // instance or not.
  3007. // =======================================================================
  3008. hRes = Exec_GetObjectByPath(pszClassName,
  3009. (lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS), pCtx,
  3010. &pClassDef, &pErrorObj);
  3011. if (FAILED(hRes))
  3012. {
  3013. OpInfo.ErrorOccurred(hRes, pErrorObj);
  3014. if (pErrorObj)
  3015. pErrorObj->Release();
  3016. return hRes;
  3017. }
  3018. CReleaseMe _3(pClassDef);
  3019. // Now see if the method exists and if the class definition
  3020. // has the [bypass_getobject] qualifier on that method.
  3021. // ========================================================
  3022. hRes = pClassDef->GetMethodQualifierSet(wszMethodName, &pQSet);
  3023. if (FAILED(hRes))
  3024. {
  3025. // Means the method doesn't even exist
  3026. if ( WBEM_E_NOT_FOUND == hRes )
  3027. {
  3028. hRes = WBEM_E_INVALID_METHOD;
  3029. }
  3030. return OpInfo.ErrorOccurred(hRes);
  3031. }
  3032. CReleaseMe _4(pQSet);
  3033. hRes = pQSet->Get(L"bypass_getobject", 0, 0, 0);
  3034. if (hRes == WBEM_E_NOT_FOUND)
  3035. {
  3036. // If here, we are going to get the object pointed to by the path first to ensure it is
  3037. // valid. Note that the object may be either an instance or class object
  3038. //
  3039. // First, merge in the __GET_EXT_KEYS_ONLY during the GetObject calls to allow
  3040. // the provider to quickly verify the existence of the object. We don't
  3041. // actually care about the property values other than the keys. We use
  3042. // a copy of the context object, as we want to merge in KEYS_ONLY behavior
  3043. // for the next call only.
  3044. // ============================================================================
  3045. IWbemClassObject *pVerifiedObj = 0;
  3046. IWbemContext *pCopy = 0;
  3047. if (pCtx)
  3048. pCtx->Clone(&pCopy);
  3049. hRes = MergeGetKeysCtx(pCopy);
  3050. if (FAILED(hRes))
  3051. return OpInfo.ErrorOccurred(hRes);
  3052. // If here, we are verifying the object exists before passing the
  3053. // control to the method handler.
  3054. // ==============================================================
  3055. hRes = Exec_GetObjectByPath(wszObjectPath, lFlags, pCopy,
  3056. &pVerifiedObj, &pErrorObj);
  3057. if (pCopy)
  3058. pCopy->Release();
  3059. if (FAILED(hRes))
  3060. {
  3061. OpInfo.ErrorOccurred(hRes, pErrorObj);
  3062. if (pErrorObj)
  3063. pErrorObj->Release();
  3064. return hRes;
  3065. }
  3066. // If here, the class or instance exists!!
  3067. // =======================================
  3068. pVerifiedObj->Release();
  3069. }
  3070. else if (FAILED(hRes))
  3071. {
  3072. return OpInfo.ErrorOccurred(hRes);
  3073. }
  3074. // If this is the special internal security object, handle it internally
  3075. // ======================================================================
  3076. CVar Value;
  3077. hRes = ((CWbemClass *) pClassDef)->GetSystemPropertyByName(L"__CLASS", &Value);
  3078. if (hRes == S_OK && Value.GetType() == VT_BSTR && !Value.IsDataNull())
  3079. if (!wbem_wcsicmp(Value.GetLPWSTR(), L"__SystemSecurity"))
  3080. return SecurityMethod(wszMethodName, lFlags, pInParams, pCtx, pSink);
  3081. // Make sure we have security.
  3082. // ===========================
  3083. if (!Allowed(WBEM_METHOD_EXECUTE))
  3084. return OpInfo.ErrorOccurred(WBEM_E_ACCESS_DENIED);
  3085. // Now, we locate the exact implementation of the method. After all, the
  3086. // subclass may have been very lazy and relied on its parent implementation,
  3087. // the way many kids rely on their parents for gas money.
  3088. // =========================================================================
  3089. hRes = GetImplementationClass(pClassDef, wszMethodName, pCtx, &pImplementationClass);
  3090. if (FAILED(hRes))
  3091. return OpInfo.ErrorOccurred(hRes);
  3092. // The "pImplementatinClass" now points to the class object where the methods is implemented
  3093. // =========================================================================================
  3094. CReleaseMe rm2(pImplementationClass);
  3095. CWbemClass * pImplementationDef = (CWbemClass*)pImplementationClass;
  3096. // Make sure that class paths are only used with static methods.
  3097. // =============================================================
  3098. CVar Var;
  3099. if (bPathIsToClassObject)
  3100. {
  3101. hRes = pImplementationDef->GetMethodQualifier(wszMethodName, L"STATIC", &Var);
  3102. if (hRes != S_OK || Var.GetBool() != VARIANT_TRUE)
  3103. {
  3104. return OpInfo.ErrorOccurred(WBEM_E_INVALID_METHOD_PARAMETERS);
  3105. }
  3106. }
  3107. // Get the provider name.
  3108. // ======================
  3109. CVar vProv;
  3110. hRes = pImplementationDef->GetQualifier(L"Provider", &vProv);
  3111. if (FAILED(hRes) || vProv.GetType() != VT_BSTR)
  3112. return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION);
  3113. // Adjust the path to reference the class of implementation
  3114. // ========================================================
  3115. CVar vImpClassName;
  3116. hRes = pImplementationDef->GetClassName(&vImpClassName);
  3117. if (FAILED(hRes) || vImpClassName.GetType() != VT_BSTR)
  3118. return OpInfo.ErrorOccurred(WBEM_E_CRITICAL_ERROR);
  3119. BSTR strNewPath = CQueryEngine::AdjustPathToClass(wszObjectPath,
  3120. vImpClassName.GetLPWSTR());
  3121. if (strNewPath == NULL)
  3122. return OpInfo.ErrorOccurred(WBEM_E_CRITICAL_ERROR);
  3123. CSysFreeMe sfm1(strNewPath);
  3124. // Load the provider and execute it.
  3125. // ==================================
  3126. CMethodSink * pMethSink = new CMethodSink(OpInfo.GetSink());
  3127. if(pMethSink == NULL)
  3128. return OpInfo.ErrorOccurred(WBEM_E_OUT_OF_MEMORY);
  3129. pMethSink->AddRef();
  3130. CReleaseMe _5(pMethSink);
  3131. // Find provider.
  3132. // ==============
  3133. IWbemServices *pProv = 0;
  3134. if(m_pProvFact == NULL)
  3135. hRes = WBEM_E_CRITICAL_ERROR;
  3136. else
  3137. {
  3138. WmiInternalContext t_InternalContext ;
  3139. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
  3140. hRes = m_pProvFact->GetProvider(
  3141. t_InternalContext ,
  3142. 0, // lFlags
  3143. pCtx,
  3144. 0,
  3145. m_wszUserName,
  3146. m_wsLocale,
  3147. 0, // IWbemPath pointer
  3148. vProv, // Provider
  3149. IID_IWbemServices,
  3150. (LPVOID *) &pProv
  3151. );
  3152. }
  3153. if (FAILED(hRes))
  3154. {
  3155. return pSink->Return(hRes);
  3156. }
  3157. CReleaseMe _(pProv);
  3158. hRes = pProv->ExecMethodAsync(
  3159. strNewPath,
  3160. wszMethodName,
  3161. lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  3162. pCtx,
  3163. pInParams,
  3164. pMethSink
  3165. );
  3166. return hRes;
  3167. }
  3168. //***************************************************************************
  3169. //
  3170. // CWbemNamespace::GetOrPutDynProps
  3171. //
  3172. // Processes an instance to see if any properties have been marked
  3173. // as 'dynamic'.
  3174. //
  3175. // Short-circuit logic is in effect. The instance as a whole must be
  3176. // marked with the following Qualifier to signal that the instance has
  3177. // dynamic properties which need evaluation:
  3178. //
  3179. // "DYNPROPS" (VT_BOOL) = VARIANT_TRUE
  3180. //
  3181. // Optionally, the instance may contain:
  3182. // "INSTANCECONTEXT" VT_BSTR = <provider specific string>
  3183. //
  3184. // In addition, each dynamic property is marked
  3185. //
  3186. // "DYNAMIC" VT_BOOL VARIANT_TRUE
  3187. // "LOCATORCLSID" VT_BSTR CLSID of the provider
  3188. // "PROPERTYCONTEXT" VT_BSTR <provider specific string>
  3189. //
  3190. // "INSTANCECONTEXT" and "PROPERTYCONTEXT" are not checked by this code,
  3191. // since they are optional for each provider.
  3192. //
  3193. // PARAMETERS:
  3194. //
  3195. // IWbemClassObject* pObj The object to fill in dynamic properties
  3196. // in.
  3197. // Operation op Can be GET or PUT depending on what is
  3198. // needed.
  3199. // bool bIsDynamic True if a dynamically provided class. Note that it
  3200. // would be very strange to have a dynamic class with
  3201. // dynamic properties.
  3202. // RETURN VALUES:
  3203. // <WBEM_NO_ERROR> No provider was involved or if a provider was
  3204. // involved, properties were all evaluated.
  3205. //
  3206. // <WBEM_E_INVALID_OBJECT>
  3207. // Object was marked as dynamic, but other Qualifiers were missing.
  3208. //
  3209. // <WBEM_E_PROVIDER_NOT_FOUND>
  3210. // One or more of the specified providers could not be found.
  3211. //
  3212. // <WBEM_E_PROVIDER_FAILURE>
  3213. // One or more providers were not able to provide the properties.
  3214. //
  3215. // <WBEM_E_CRITICAL_ERROR>
  3216. //
  3217. //***************************************************************************
  3218. HRESULT CWbemNamespace::GetOrPutDynProps(
  3219. IWbemClassObject *pObj,
  3220. Operation op,
  3221. BOOL bIsDynamic
  3222. )
  3223. {
  3224. HRESULT hRes;
  3225. IWbemContext *pCtx = 0;
  3226. CVar vDynTest;
  3227. _IWmiDynamicPropertyResolver *pResolver = 0;
  3228. IWbemQualifierSet *pQSet = 0;
  3229. IWbemClassObject *pClassDef = 0;
  3230. CVARIANT v;
  3231. // Examine the instance to see if there are any dynamic properties.
  3232. // ================================================================
  3233. hRes = pObj->GetQualifierSet(&pQSet);
  3234. if (FAILED(hRes))
  3235. return WBEM_NO_ERROR;
  3236. CReleaseMe _1(pQSet);
  3237. hRes = pQSet->Get(L"DYNPROPS", 0, &v, 0);
  3238. if (FAILED(hRes))
  3239. return WBEM_S_NO_ERROR;
  3240. if (v.GetBool() == FALSE)
  3241. return WBEM_S_NO_ERROR;
  3242. v.Clear();
  3243. hRes = pObj->Get(L"__CLASS", 0, &v, 0, 0);
  3244. if (FAILED(hRes))
  3245. return hRes;
  3246. // Get the class definition for the object.
  3247. // Must be static.
  3248. // ========================================
  3249. hRes = CRepository::GetObject(
  3250. m_pSession,
  3251. m_pNsHandle,
  3252. v.GetStr(),
  3253. 0,
  3254. &pClassDef
  3255. );
  3256. CReleaseMe _2(pClassDef);
  3257. if (FAILED(hRes))
  3258. return hRes;
  3259. // Access provider subsystem to do the dirty work.
  3260. // ================================================
  3261. if (m_pProvFact == NULL)
  3262. hRes = WBEM_E_CRITICAL_ERROR;
  3263. else
  3264. {
  3265. pCtx = ConfigMgr::GetNewContext();
  3266. if ( pCtx == NULL )
  3267. return WBEM_E_OUT_OF_MEMORY;
  3268. hRes = m_pProvFact->GetDynamicPropertyResolver (
  3269. 0, // lFlags
  3270. pCtx, // context
  3271. m_wszUserName,
  3272. m_wsLocale,
  3273. IID__IWmiDynamicPropertyResolver,
  3274. (LPVOID *)&pResolver);
  3275. }
  3276. CReleaseMe _1_pCtx (pCtx) ;
  3277. if (FAILED(hRes))
  3278. return hRes;
  3279. CReleaseMe _3(pResolver);
  3280. // Determine if a put or a get.
  3281. // ============================
  3282. if (op == GET)
  3283. {
  3284. hRes = pResolver->Read(pCtx, pClassDef, &pObj);
  3285. }
  3286. else if (op == PUT)
  3287. {
  3288. hRes = pResolver->Write(pCtx, pClassDef, pObj);
  3289. }
  3290. else
  3291. return WBEM_E_INVALID_PARAMETER;
  3292. return hRes;
  3293. }
  3294. //***************************************************************************
  3295. //
  3296. // AddKey
  3297. //
  3298. // Adds a keyname/value pair to a normalized path
  3299. //
  3300. // throw CX_MemoryException
  3301. //
  3302. //***************************************************************************
  3303. HRESULT AddKey(WString & wNormalString, WCHAR * pwsKeyName, VARIANT *pvKeyValue,
  3304. int & iNumKey, CWbemInstance* pClassDef)
  3305. {
  3306. if(iNumKey++ > 0)
  3307. wNormalString += L","; // prepend comma for all but the first key
  3308. wNormalString += pwsKeyName;
  3309. wNormalString += "=";
  3310. if(pvKeyValue->vt == VT_BSTR)
  3311. {
  3312. wNormalString += L"\"";
  3313. // if there are any quotes, they must be prepended with a back slash;
  3314. // Also, any back slashes should be doubled up.
  3315. int iLen = 1; // one for the terminator;
  3316. WCHAR * pTest;
  3317. for(pTest = pvKeyValue->bstrVal;*pTest; pTest++, iLen++)
  3318. if(*pTest == L'\"' || *pTest == L'\\')
  3319. iLen++;
  3320. WCHAR * pString = new WCHAR[iLen];
  3321. if(pString == NULL)
  3322. throw CX_MemoryException();
  3323. wmilib::auto_buffer<WCHAR> rm_(pString);
  3324. WCHAR * pTo = pString;
  3325. for(pTest = pvKeyValue->bstrVal;*pTest; pTest++, pTo++)
  3326. {
  3327. if(*pTest == L'\"' || *pTest == L'\\')
  3328. {
  3329. *pTo = L'\\';
  3330. pTo++;
  3331. }
  3332. *pTo = *pTest;
  3333. }
  3334. *pTo = 0;
  3335. wNormalString += pString;
  3336. wNormalString += L"\"";
  3337. return S_OK;
  3338. }
  3339. if(pvKeyValue->vt != VT_EMPTY && pvKeyValue->vt != VT_NULL)
  3340. {
  3341. // special case for large unsigned numbers
  3342. if(pvKeyValue->vt == VT_I4 && pvKeyValue->lVal < 0)
  3343. {
  3344. CIMTYPE ct;
  3345. HRESULT hRes = pClassDef->Get(pwsKeyName, 0, NULL, &ct, NULL);
  3346. if(hRes == S_OK && ct == CIM_UINT32)
  3347. {
  3348. WCHAR wBuff[32];
  3349. StringCchPrintfW(wBuff, 32, L"%u",pvKeyValue->lVal);
  3350. wNormalString += wBuff;
  3351. return S_OK;
  3352. }
  3353. }
  3354. _variant_t var;
  3355. HRESULT hRes = VariantChangeType(&var, pvKeyValue, 0, VT_BSTR);
  3356. if(hRes == S_OK)
  3357. {
  3358. wNormalString += var.bstrVal;
  3359. }
  3360. return hRes;
  3361. }
  3362. return WBEM_E_INVALID_OBJECT_PATH;
  3363. }
  3364. //***************************************************************************
  3365. //
  3366. // NormalizeObjectPath
  3367. //
  3368. // Creates a normalized object path for passing to providers.
  3369. //***************************************************************************
  3370. HRESULT NormalizeObjectPath(ParsedObjectPath*pOutput, WString & wNormalString,
  3371. CWbemInstance* pClassDef)
  3372. {
  3373. try
  3374. {
  3375. HRESULT hRes;
  3376. // For singleton, so long as the class is singleton
  3377. if(pOutput->m_bSingletonObj)
  3378. {
  3379. CVar Singleton;
  3380. hRes = pClassDef->GetQualifier(L"SINGLETON", &Singleton);
  3381. if (hRes == 0 && Singleton.GetBool() != 0)
  3382. {
  3383. wNormalString = pOutput->m_pClass;
  3384. wNormalString += "=@";
  3385. return S_OK;
  3386. }
  3387. else
  3388. return WBEM_E_INVALID_OBJECT_PATH;
  3389. }
  3390. int iKeyNum = 0;
  3391. int iNumMatch = 0; // number of keys in the path which were found in the class def
  3392. // Start off by writting the class name followe by a dot
  3393. wNormalString = pOutput->m_pClass;
  3394. wNormalString += L".";
  3395. CWStringArray ClassKeyNames;
  3396. if(!pClassDef->GetKeyProps(ClassKeyNames))
  3397. return WBEM_E_INVALID_CLASS;
  3398. // For each key in the class definition
  3399. for(int iClassKey = 0; iClassKey < ClassKeyNames.Size(); iClassKey++)
  3400. {
  3401. // look for the class key in the path
  3402. bool bClassKeyIsInPath = false;
  3403. int iPathKey;
  3404. for(iPathKey = 0; iPathKey < pOutput->m_dwNumKeys; iPathKey++)
  3405. {
  3406. KeyRef * key = pOutput->m_paKeys[iPathKey];
  3407. if(key->m_pName == 0 && ClassKeyNames.Size() == 1 && pOutput->m_dwNumKeys==1)
  3408. {
  3409. bClassKeyIsInPath = true;
  3410. break;
  3411. }
  3412. else if(key->m_pName && !wbem_wcsicmp(key->m_pName, ClassKeyNames[iClassKey]))
  3413. {
  3414. bClassKeyIsInPath = true;
  3415. break;
  3416. }
  3417. }
  3418. if(bClassKeyIsInPath)
  3419. {
  3420. iNumMatch++;
  3421. // todo, check type
  3422. KeyRef * key = pOutput->m_paKeys[iPathKey];
  3423. hRes = AddKey(wNormalString, ClassKeyNames[iClassKey],
  3424. &key->m_vValue, iKeyNum, pClassDef);
  3425. if(FAILED(hRes))
  3426. return hRes;
  3427. }
  3428. else
  3429. {
  3430. // If the key has a default value, then use it
  3431. _variant_t var;
  3432. hRes = pClassDef->Get(ClassKeyNames[iClassKey], 0, &var, NULL, NULL);
  3433. if(FAILED(hRes) || var.vt == VT_EMPTY || var.vt == VT_NULL)
  3434. return WBEM_E_INVALID_OBJECT_PATH;
  3435. hRes = AddKey(wNormalString, ClassKeyNames[iClassKey], &var, iKeyNum,pClassDef);
  3436. if(FAILED(hRes))
  3437. return hRes;
  3438. }
  3439. }
  3440. if(iNumMatch == pOutput->m_dwNumKeys)
  3441. return S_OK;
  3442. else
  3443. return WBEM_E_INVALID_OBJECT_PATH;
  3444. }
  3445. catch (CX_MemoryException &)
  3446. {
  3447. return WBEM_E_OUT_OF_MEMORY;
  3448. }
  3449. }
  3450. //***************************************************************************
  3451. //
  3452. // CWbemNamespace::DynAux_GetInstance
  3453. //
  3454. // Retrieves an instance identified by its path from the dynamic provider
  3455. // registered for that class.
  3456. //
  3457. // PARAMETERS:
  3458. //
  3459. // IN DWORD dwNamespace Namespace handle to the current
  3460. // namespace (see objdb.h)
  3461. // IN LPWSTR pObjectPath Object path to the instance.
  3462. // IN long lFlags Flags. Propagated to provider.
  3463. // OUT IWbemClassObject** pObj Destination for the class definition.
  3464. // The caller must release this object
  3465. // if the call is successful.
  3466. // OUT IWbemClassObject** ppErrorObj Destination for the error object. May
  3467. // be NULL. Otherwise, the returned
  3468. // pointer must be released if not NULL.
  3469. // RETURN VALUES:
  3470. //
  3471. // WBEM_S_NO_ERROR Success.
  3472. // WBEM_E_NOT_FOUND No such instance, says provider, or the
  3473. // class is not dynamic.
  3474. // WBEM_E_INVALID_PARAMETER One or more parameters are invalid.
  3475. // WBEM_E_INVALID_CLASS The class specified in the path does not
  3476. // exist.
  3477. // WBEM_E_FAILED Unexpected error occured.
  3478. // WBEM_E_PROVIDER_NOT_FOUND Provider for this class could not be
  3479. // located --- not registered with us or COM.
  3480. // WBEM_E_PROVIDER_FAILURE Provider reported an error while looking
  3481. // for this object.
  3482. // WBEM_E_PROVIDER_NOT_CAPABLE Provider for this class is not capable of
  3483. // getting objects by path.
  3484. //
  3485. //***************************************************************************
  3486. HRESULT CWbemNamespace::DynAux_GetInstance(
  3487. IN LPWSTR wszObjectPath,
  3488. IN long lFlags,
  3489. IN IWbemContext* pCtx,
  3490. IN CBasicObjectSink* pSink
  3491. )
  3492. {
  3493. // Parse the object path to get the class involved.
  3494. // ================================================
  3495. ParsedObjectPath* pOutput = 0;
  3496. CObjectPathParser p;
  3497. int nStatus = p.Parse(wszObjectPath, &pOutput);
  3498. OnDeleteObj<ParsedObjectPath*,CObjectPathParser,
  3499. void (CObjectPathParser:: *)(ParsedObjectPath *),
  3500. &CObjectPathParser::Free> FreeMe(&p,pOutput);
  3501. if(CObjectPathParser::NoError != nStatus || !pOutput->IsInstance())
  3502. return pSink->Return(WBEM_E_INVALID_OBJECT_PATH);
  3503. HRESULT hres = WBEM_E_FAILED;
  3504. IWbemClassObject* pErrorObj = NULL;
  3505. CReleaseMeRef<IWbemClassObject*> rmErrObj(pErrorObj);
  3506. CSetStatusOnMe SetMe(pSink,hres,pErrorObj);
  3507. // See if this class is actually provided dynamically
  3508. BSTR strClass = SysAllocString(pOutput->m_pClass);
  3509. if (NULL == strClass)
  3510. {
  3511. return hres = WBEM_E_OUT_OF_MEMORY;
  3512. }
  3513. CSysFreeMe sfm(strClass);
  3514. CWbemInstance *pClassDef = 0;
  3515. IWbemClassObject* pClassObj = NULL;
  3516. hres = Exec_GetObjectByPath(strClass,
  3517. lFlags & WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  3518. pCtx,&pClassObj, NULL);
  3519. if(FAILED(hres))
  3520. {
  3521. hres = (hres == WBEM_E_NOT_FOUND) ? WBEM_E_INVALID_CLASS : WBEM_E_FAILED;
  3522. return hres;
  3523. }
  3524. CReleaseMe rm(pClassObj);
  3525. pClassDef = (CWbemInstance*)pClassObj;
  3526. WString wNormalPath;
  3527. hres = NormalizeObjectPath(pOutput, wNormalPath, pClassDef);
  3528. if(FAILED(hres)) return hres;
  3529. if(!pClassDef->IsKeyed())
  3530. return hres = WBEM_E_INVALID_CLASS;
  3531. // Make sure that this class is not static ---
  3532. // i.e. either dynamic or abstract
  3533. // ===========================================
  3534. CVar vDynamic;
  3535. hres = pClassDef->GetQualifier(L"Dynamic", &vDynamic);
  3536. if(FAILED(hres) || vDynamic.GetType() != VT_BOOL || !vDynamic.GetBool())
  3537. {
  3538. // Not dynamic. Check if it is abstract
  3539. // ====================================
  3540. CVar vAbstract;
  3541. hres = pClassDef->GetQualifier(L"Abstract", &vAbstract);
  3542. if(FAILED(hres) || vAbstract.GetType() != VT_BOOL || !vAbstract.GetBool())
  3543. return hres = WBEM_E_NOT_FOUND;
  3544. }
  3545. // Build the class hierarchy
  3546. // =========================
  3547. wmilib::auto_ptr<CDynasty> pDynasty;
  3548. hres = DynAux_BuildClassHierarchy(strClass, lFlags, pCtx, pDynasty,&pErrorObj);
  3549. if(FAILED(hres)) return hres;
  3550. rmErrObj.release(); // set it to null anyway
  3551. // If direct read is requested, only ask the provider in question.
  3552. // ===============================================================
  3553. if (lFlags & WBEM_FLAG_DIRECT_READ)
  3554. {
  3555. DynAux_GetSingleInstance((CWbemClass*) pClassObj,lFlags, wszObjectPath, pCtx, pSink);
  3556. }
  3557. else
  3558. {
  3559. // Create merging sink
  3560. hres = WBEM_E_OUT_OF_MEMORY; // pre-set the failure
  3561. CSingleMergingSink* pMergeSink = new CSingleMergingSink(pSink, strClass); // throw
  3562. if(pMergeSink == NULL) return hres;
  3563. pMergeSink->AddRef();
  3564. CReleaseMe rm(pMergeSink);
  3565. // Ask all providers
  3566. DynAux_AskRecursively(pDynasty.get(), lFlags, wNormalPath, pCtx,pMergeSink);
  3567. }
  3568. SetMe.dismiss();
  3569. return WBEM_S_NO_ERROR;
  3570. }
  3571. //***************************************************************************
  3572. //
  3573. //***************************************************************************
  3574. HRESULT CWbemNamespace::DynAux_AskRecursively(CDynasty* pDynasty,
  3575. long lFlags,
  3576. LPWSTR wszObjectPath,
  3577. IWbemContext* pCtx,
  3578. CBasicObjectSink* pSink)
  3579. {
  3580. // Convert the path to the new class
  3581. // =================================
  3582. BSTR strNewPath = CQueryEngine::AdjustPathToClass(wszObjectPath, pDynasty->m_wszClassName);
  3583. if(strNewPath == NULL) return pSink->Return(WBEM_E_INVALID_OBJECT_PATH);
  3584. CSysFreeMe sfm(strNewPath);
  3585. // Get this provider's object
  3586. // ==========================
  3587. DynAux_GetSingleInstance((CWbemClass*)pDynasty->m_pClassObj,lFlags, strNewPath, pCtx, pSink);
  3588. // Get the children's objects
  3589. // ==========================
  3590. for(int i = 0; i < pDynasty->m_Children.Size(); i++)
  3591. {
  3592. CDynasty* pChildDyn = (CDynasty*)pDynasty->m_Children.GetAt(i);
  3593. DynAux_AskRecursively(pChildDyn, lFlags, wszObjectPath, pCtx,pSink);
  3594. }
  3595. return WBEM_S_NO_ERROR;
  3596. }
  3597. //***************************************************************************
  3598. //
  3599. //***************************************************************************
  3600. HRESULT CWbemNamespace::DynAux_GetSingleInstance(CWbemClass* pClassDef,
  3601. long lFlags,
  3602. LPWSTR wszObjectPath,
  3603. IWbemContext* pCtx,
  3604. CBasicObjectSink* pSink)
  3605. {
  3606. COperationError OpInfo(pSink, L"GetObject", wszObjectPath, FALSE);
  3607. // the ctor calls setstatus in bad luck case
  3608. if (!OpInfo.IsOk()) return WBEM_E_OUT_OF_MEMORY;
  3609. // Verify that the class is indeed dynamic
  3610. // =======================================
  3611. if(!pClassDef->IsDynamic())
  3612. return OpInfo.ErrorOccurred(WBEM_E_NOT_FOUND);
  3613. CVar vProvName;
  3614. HRESULT hres = pClassDef->GetQualifier(L"Provider", &vProvName);
  3615. if(FAILED(hres) || vProvName.GetType() != VT_BSTR)
  3616. return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION);
  3617. OpInfo.SetProviderName(vProvName.GetLPWSTR()); //throw
  3618. // Access the provider cache.
  3619. // ==========================
  3620. IWbemServices *pProv = 0;
  3621. HRESULT hRes;
  3622. if(m_pProvFact == NULL)
  3623. hRes = WBEM_E_CRITICAL_ERROR;
  3624. else
  3625. {
  3626. WmiInternalContext t_InternalContext ;
  3627. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
  3628. hRes = m_pProvFact->GetProvider(
  3629. t_InternalContext ,
  3630. 0, // lFlags
  3631. pCtx,
  3632. 0,
  3633. m_wszUserName,
  3634. m_wsLocale,
  3635. 0, // IWbemPath pointer
  3636. vProvName, // Provider
  3637. IID_IWbemServices,
  3638. (LPVOID *) &pProv
  3639. );
  3640. }
  3641. if (FAILED(hRes))
  3642. {
  3643. return pSink->Return(hRes);
  3644. }
  3645. CReleaseMe _(pProv);
  3646. CDecoratingSink * pDecore = new CDecoratingSink(OpInfo.GetSink(), this);
  3647. if(pDecore == NULL) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  3648. pDecore->AddRef();
  3649. CReleaseMe cdecor(pDecore);
  3650. hRes = pProv->GetObjectAsync(wszObjectPath, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pDecore);
  3651. return hRes;
  3652. }
  3653. //***************************************************************************
  3654. //
  3655. // CWbemNamespace::DynAux_GetInstances
  3656. //
  3657. // Gets all instances from the provider specified in the class
  3658. // definition. Does no inheritance joins; this is a simple retrieval
  3659. // of all instances from the specified class.
  3660. //
  3661. // Preconditions:
  3662. // 1. The class <pClassDef> is known to be marked 'dynamic', but no
  3663. // other verification has been done on the class definition.
  3664. // 2. <pClassDef> is not NULL.
  3665. //
  3666. // Postconditions:
  3667. // 1. <aInstances> is empty on all error conditions.
  3668. //
  3669. // PARAMETERS:
  3670. //
  3671. // READONLY CWbemObject *pClassDef The definition of the class to retrieve
  3672. // instances of.
  3673. // long lFlags The flags (deep/shallow)
  3674. // CFlexArray &aInstances Destination for the instances.
  3675. // IWbemClassObject** ppErrorObj Destination for the error object. If
  3676. // not NULL, an error object may be placed
  3677. // here. It is the caller's responsibility
  3678. // to release it if not NULL.
  3679. // RETURN VALUES:
  3680. //
  3681. // WBEM_NO_ERROR No errors. This includes a no-error situation
  3682. // with zero instances returned.
  3683. // WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
  3684. // class is incomplete.
  3685. // WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
  3686. // registered with us or with COM.
  3687. // WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
  3688. // instances.
  3689. // WBEM_E_FAILED Unexpected error has occured.
  3690. //
  3691. //***************************************************************************
  3692. HRESULT CWbemNamespace::DynAux_GetInstances(
  3693. READONLY CWbemObject *pClassDef,
  3694. long lFlags,
  3695. IWbemContext* pCtx,
  3696. CBasicObjectSink* pSink ,
  3697. BOOL bComplexQuery
  3698. )
  3699. {
  3700. // First, get the current task -
  3701. // if there isn't one, then we are on an WbemESS thread
  3702. // ESS use to issue "internal" queries that are processes without arbitration
  3703. CWbemRequest* pCurrReq = CWbemQueue::GetCurrentRequest();
  3704. CWmiTask * pCurrTask = pCurrReq?((CWmiTask *)pCurrReq->m_phTask):NULL;
  3705. // We'll need the finalizer in case we need to cancel something
  3706. HRESULT hr;
  3707. _IWmiFinalizer* pMainFnz = NULL;
  3708. if (pCurrTask)
  3709. {
  3710. hr = pCurrTask->GetFinalizer( &pMainFnz );
  3711. if (FAILED(hr)) return hr;
  3712. }
  3713. CReleaseMe rm( pMainFnz );
  3714. CWmiMerger* pWmiMerger = NULL;
  3715. // Check if query arbitration is enabled
  3716. if ( ConfigMgr::GetEnableQueryArbitration() && pCurrTask)
  3717. {
  3718. // Get the arbitrated query pointer and cast to a merger as appropriate
  3719. _IWmiArbitratedQuery* pArbQuery = NULL;
  3720. hr = pCurrTask->GetArbitratedQuery( 0L, &pArbQuery );
  3721. if ( SUCCEEDED( hr ) )
  3722. {
  3723. hr = pArbQuery->IsMerger();
  3724. if ( SUCCEEDED( hr ) )
  3725. {
  3726. pWmiMerger = (CWmiMerger*) pArbQuery;
  3727. }
  3728. else
  3729. {
  3730. pArbQuery->Release();
  3731. }
  3732. }
  3733. // Clear errors
  3734. hr = WBEM_S_NO_ERROR;
  3735. } // IF Query arbitration enabled
  3736. CReleaseMe rmMerger( (_IWmiArbitratee*) pWmiMerger );
  3737. // Perform correct handling based on whether or not we have a merger
  3738. if ( pWmiMerger )
  3739. {
  3740. hr = pWmiMerger->RegisterArbitratedInstRequest( pClassDef, lFlags, pCtx, pSink, bComplexQuery, this );
  3741. if (FAILED( hr))
  3742. if (pMainFnz) pMainFnz->CancelTask( 0 );
  3743. return hr;
  3744. }
  3745. //
  3746. // when the query arbitration is not enabled we fall here
  3747. //
  3748. CAsyncReq_DynAux_GetInstances * pReq;
  3749. pReq = new CAsyncReq_DynAux_GetInstances (this,
  3750. pClassDef,
  3751. lFlags,
  3752. pCtx,
  3753. pSink);
  3754. if ( pReq == NULL)
  3755. {
  3756. if (pMainFnz) pMainFnz->CancelTask ( 0 );
  3757. return WBEM_E_OUT_OF_MEMORY;
  3758. }
  3759. if ( NULL == pReq->GetContext() )
  3760. {
  3761. if (pMainFnz) pMainFnz->CancelTask ( 0 );
  3762. delete pReq;
  3763. return WBEM_E_OUT_OF_MEMORY;
  3764. }
  3765. // Set the task for the request - we'll just use the existing one if any
  3766. pReq->m_phTask = pCurrTask;
  3767. if (pReq->m_phTask) pReq->m_phTask->AddRef();
  3768. hr = ConfigMgr::EnqueueRequest(pReq);
  3769. if (FAILED(hr))
  3770. {
  3771. if (pMainFnz) pMainFnz->CancelTask ( 0 );
  3772. delete pReq;
  3773. }
  3774. return hr;
  3775. }
  3776. //***************************************************************************
  3777. //
  3778. // CWbemNamespace::DynAux_GetInstances
  3779. //
  3780. // Gets all instances from the provider specified in the class
  3781. // definition. Does no inheritance joins; this is a simple retrieval
  3782. // of all instances from the specified class.
  3783. //
  3784. // Preconditions:
  3785. // 1. The class <pClassDef> is known to be marked 'dynamic', but no
  3786. // other verification has been done on the class definition.
  3787. // 2. <pClassDef> is not NULL.
  3788. //
  3789. // Postconditions:
  3790. // 1. <aInstances> is empty on all error conditions.
  3791. //
  3792. // PARAMETERS:
  3793. //
  3794. // READONLY CWbemObject *pClassDef The definition of the class to retrieve
  3795. // instances of.
  3796. // long lFlags The flags (deep/shallow)
  3797. // CFlexArray &aInstances Destination for the instances.
  3798. // IWbemClassObject** ppErrorObj Destination for the error object. If
  3799. // not NULL, an error object may be placed
  3800. // here. It is the caller's responsibility
  3801. // to release it if not NULL.
  3802. // RETURN VALUES:
  3803. //
  3804. // WBEM_NO_ERROR No errors. This includes a no-error situation
  3805. // with zero instances returned.
  3806. // WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
  3807. // class is incomplete.
  3808. // WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
  3809. // registered with us or with COM.
  3810. // WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
  3811. // instances.
  3812. // WBEM_E_FAILED Unexpected error has occured.
  3813. //
  3814. //***************************************************************************
  3815. HRESULT CWbemNamespace::Exec_DynAux_GetInstances(
  3816. READONLY CWbemObject *pClassDef,
  3817. long lFlags,
  3818. IWbemContext* pCtx,
  3819. CBasicObjectSink* pSink
  3820. )
  3821. {
  3822. COperationError OpInfo(pSink, L"CreateInstanceEnum", L"", FALSE);
  3823. if ( !OpInfo.IsOk() ) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  3824. CVar vProv;
  3825. CVar vClassName;
  3826. // Get the provider name.
  3827. // ======================
  3828. try // internal fastprox interfaces throw
  3829. {
  3830. HRESULT hres = pClassDef->GetQualifier(L"Provider", &vProv);
  3831. if (FAILED(hres) || vProv.GetType() != VT_BSTR)
  3832. return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION);
  3833. if (FAILED(pClassDef->GetClassName(&vClassName)))
  3834. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  3835. OpInfo.SetParameterInfo(vClassName.GetLPWSTR());
  3836. }
  3837. catch(CX_MemoryException &)
  3838. {
  3839. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  3840. }
  3841. // Access Provider Subsystem.
  3842. // ==========================
  3843. IWbemServices *pProv = 0;
  3844. HRESULT hRes;
  3845. if (m_pProvFact == NULL)
  3846. hRes = WBEM_E_CRITICAL_ERROR;
  3847. else
  3848. {
  3849. WmiInternalContext t_InternalContext ;
  3850. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) );
  3851. hRes = m_pProvFact->GetProvider(
  3852. t_InternalContext ,
  3853. 0, // lFlags
  3854. pCtx,
  3855. 0,
  3856. m_wszUserName,
  3857. m_wsLocale,
  3858. 0, // IWbemPath pointer
  3859. vProv, // Provider
  3860. IID_IWbemServices,
  3861. (LPVOID *) &pProv);
  3862. }
  3863. if (FAILED(hRes))
  3864. return pSink->Return(hRes);
  3865. CReleaseMe _1(pProv);
  3866. // Set up the sink chain to be delivered to the provider.
  3867. // The code & destruct sequence is critical and the
  3868. // refcounting is very carefully thought out. Do not
  3869. // change this code unless you know exactly what you are
  3870. // doing. And don't even change it then.
  3871. // ======================================================
  3872. CProviderSink *pProvSink = new CProviderSink(1, vClassName.GetLPWSTR());
  3873. if (pProvSink == 0)
  3874. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  3875. CReleaseMe _3(pProvSink);
  3876. CDecoratingSink * pDecore = new CDecoratingSink(pSink, this);
  3877. if (pDecore == NULL)
  3878. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  3879. pProvSink->SetNextSink(pDecore);
  3880. // Before calling the provider, map the provider to the
  3881. // task so that we can cancel it proactively, if required.
  3882. // =======================================================
  3883. hRes = ((CWmiArbitrator *) m_pArb)->MapProviderToTask(0, pCtx, pProv, pProvSink);
  3884. if (FAILED(hRes))
  3885. return pSink->Return(hRes);
  3886. // Now tell the provider to start enumerating.
  3887. hRes = pProv->CreateInstanceEnumAsync(vClassName.GetLPWSTR(),
  3888. lFlags & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  3889. pCtx,
  3890. pProvSink
  3891. );
  3892. return hRes;
  3893. }
  3894. //***************************************************************************
  3895. //
  3896. // CWbemNamespace::DynAux_ExecQueryAsync
  3897. //
  3898. // Executes a SQL-1 query against a dynamic instance provider for the class
  3899. // in the query.
  3900. //
  3901. // PARAMETERS:
  3902. //
  3903. // IN DWORD dwNamespace Namespace handle to the current
  3904. // namespace (see objdb.h)
  3905. // IN CWbemObject* pClassDef Class definition of the class in the
  3906. // query. Must be dynamic.
  3907. // IN LPWSTR Query The query string.
  3908. // IN LPWSTR QueryFormat The query language. Must be WQL.
  3909. // IN long lFlags The flags. Not used.
  3910. // OUT CFlexArray &aInstances Destinatino for the instances found.
  3911. // OUT IWbemClassObject** ppErrorObj Destination for the error object. IF
  3912. // not NULL, an error object may be placed
  3913. // here. In this case, it is the caller's
  3914. // responsibility to release it.
  3915. // RETURN VALUES:
  3916. //
  3917. // WBEM_S_NO_ERROR Success (even though there may not be
  3918. // any instances).
  3919. // WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
  3920. // class is incomplete.
  3921. // WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
  3922. // registered with us or with COM.
  3923. // WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
  3924. // instances.
  3925. // WBEM_E_FAILED Unexpected error has occured.
  3926. //
  3927. //***************************************************************************
  3928. HRESULT CWbemNamespace::DynAux_ExecQueryAsync (
  3929. CWbemObject* pClassDef,
  3930. LPWSTR Query,
  3931. LPWSTR QueryFormat,
  3932. long lFlags,
  3933. IWbemContext* pCtx,
  3934. CBasicObjectSink* pSink,
  3935. BOOL bComplexQuery
  3936. )
  3937. {
  3938. // First, get the current task - if there isn't one, something
  3939. // is very wrong.
  3940. CWbemRequest* pCurrReq = CWbemQueue::GetCurrentRequest();
  3941. _DBG_ASSERT( NULL != pCurrReq && NULL != pCurrReq->m_phTask );
  3942. if ( NULL == pCurrReq || NULL == pCurrReq->m_phTask )
  3943. {
  3944. return WBEM_E_FAILED;
  3945. }
  3946. // We'll need the finalizer in case we need to cancel something
  3947. _IWmiFinalizer* pMainFnz = NULL;
  3948. HRESULT hr = ((CWmiTask*) pCurrReq->m_phTask)->GetFinalizer( &pMainFnz );
  3949. CReleaseMe rm( pMainFnz );
  3950. if ( SUCCEEDED( hr ) )
  3951. {
  3952. CWmiMerger* pWmiMerger = NULL;
  3953. // Check if query arbitration is enabled
  3954. if ( ConfigMgr::GetEnableQueryArbitration() )
  3955. {
  3956. // Get the arbitrated query pointer and cast to a merger as appropriate
  3957. _IWmiArbitratedQuery* pArbQuery = NULL;
  3958. hr = ((CWmiTask*) pCurrReq->m_phTask)->GetArbitratedQuery( 0L, &pArbQuery );
  3959. if ( SUCCEEDED( hr ) )
  3960. {
  3961. hr = pArbQuery->IsMerger();
  3962. if ( SUCCEEDED( hr ) )
  3963. {
  3964. pWmiMerger = (CWmiMerger*) pArbQuery;
  3965. }
  3966. else
  3967. {
  3968. pArbQuery->Release();
  3969. }
  3970. }
  3971. // Clear errors
  3972. hr = WBEM_S_NO_ERROR;
  3973. } // IF Query arbitration enabled
  3974. // Auto cleanup
  3975. CReleaseMe rm( (_IWmiArbitratee*) pWmiMerger );
  3976. // Perform correct handling based on whether or not we have a merger
  3977. if ( NULL != pWmiMerger )
  3978. {
  3979. hr = pWmiMerger->RegisterArbitratedQueryRequest( pClassDef, lFlags, Query, QueryFormat, pCtx, pSink, this );
  3980. if (FAILED(hr))
  3981. {
  3982. pMainFnz->CancelTask ( 0 );
  3983. }
  3984. }
  3985. else
  3986. {
  3987. CAsyncReq_DynAux_ExecQueryAsync *pReq = 0;
  3988. try
  3989. {
  3990. pReq = new CAsyncReq_DynAux_ExecQueryAsync (
  3991. this,
  3992. pClassDef,
  3993. Query,
  3994. QueryFormat,
  3995. lFlags,
  3996. pCtx,
  3997. pSink
  3998. );
  3999. }
  4000. catch(CX_Exception &)
  4001. {
  4002. pReq = 0;
  4003. }
  4004. if (pReq == NULL)
  4005. {
  4006. pMainFnz->CancelTask ( 0 );
  4007. return WBEM_E_OUT_OF_MEMORY;
  4008. }
  4009. if ( NULL == pReq->GetContext() )
  4010. {
  4011. pMainFnz->CancelTask ( 0 );
  4012. delete pReq;
  4013. return WBEM_E_OUT_OF_MEMORY;
  4014. }
  4015. hr = pReq->Initialize () ;
  4016. if ( SUCCEEDED ( hr ) )
  4017. {
  4018. // Set the task for the request - we'll just use the existing one
  4019. pCurrReq->m_phTask->AddRef();
  4020. pReq->m_phTask = pCurrReq->m_phTask;
  4021. hr = ConfigMgr::EnqueueRequest(pReq);
  4022. if (FAILED(hr))
  4023. {
  4024. pMainFnz->CancelTask ( 0 );
  4025. delete pReq;
  4026. }
  4027. } // IF Request Initialized
  4028. else
  4029. {
  4030. pMainFnz->CancelTask ( 0 );
  4031. delete pReq;
  4032. }
  4033. }
  4034. }
  4035. return hr;
  4036. }
  4037. //***************************************************************************
  4038. //
  4039. // CWbemNamespace::DynAux_ExecQueryAsync
  4040. //
  4041. // Executes a SQL-1 query against a dynamic instance provider for the class
  4042. // in the query.
  4043. //
  4044. // PARAMETERS:
  4045. //
  4046. // IN DWORD dwNamespace Namespace handle to the current
  4047. // namespace (see objdb.h)
  4048. // IN CWbemObject* pClassDef Class definition of the class in the
  4049. // query. Must be dynamic.
  4050. // IN LPWSTR Query The query string.
  4051. // IN LPWSTR QueryFormat The query language. Must be WQL.
  4052. // IN long lFlags The flags. Not used.
  4053. // OUT CFlexArray &aInstances Destinatino for the instances found.
  4054. // OUT IWbemClassObject** ppErrorObj Destination for the error object. IF
  4055. // not NULL, an error object may be placed
  4056. // here. In this case, it is the caller's
  4057. // responsibility to release it.
  4058. // RETURN VALUES:
  4059. //
  4060. // WBEM_S_NO_ERROR Success (even though there may not be
  4061. // any instances).
  4062. // WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
  4063. // class is incomplete.
  4064. // WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
  4065. // registered with us or with COM.
  4066. // WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
  4067. // instances.
  4068. // WBEM_E_FAILED Unexpected error has occured.
  4069. //
  4070. //***************************************************************************
  4071. HRESULT CWbemNamespace::Exec_DynAux_ExecQueryAsync (
  4072. CWbemObject* pClassDef,
  4073. LPWSTR Query,
  4074. LPWSTR QueryFormat,
  4075. long lFlags,
  4076. IWbemContext* pCtx,
  4077. CBasicObjectSink* pSink
  4078. )
  4079. {
  4080. COperationError OpInfo(pSink, L"ExecQuery", Query, FALSE);
  4081. if (! OpInfo.IsOk()) return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  4082. // Get the provider name.
  4083. // ======================
  4084. CVar vProv;
  4085. HRESULT hres = pClassDef->GetQualifier(L"Provider", &vProv);
  4086. if (FAILED(hres) || vProv.GetType() != VT_BSTR)
  4087. return OpInfo.ErrorOccurred(WBEM_E_INVALID_PROVIDER_REGISTRATION);
  4088. // Access the provider cache.
  4089. // ==========================
  4090. IWbemServices *pProv = 0;
  4091. HRESULT hRes;
  4092. if(m_pProvFact == NULL)
  4093. hRes = WBEM_E_CRITICAL_ERROR;
  4094. else
  4095. {
  4096. WmiInternalContext t_InternalContext ;
  4097. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
  4098. hRes = m_pProvFact->GetProvider(
  4099. t_InternalContext ,
  4100. 0, // lFlags
  4101. pCtx,
  4102. 0,
  4103. m_wszUserName,
  4104. m_wsLocale,
  4105. 0, // IWbemPath pointer
  4106. vProv, // Provider
  4107. IID_IWbemServices,
  4108. (LPVOID *) &pProv
  4109. );
  4110. }
  4111. if (FAILED(hRes))
  4112. {
  4113. return pSink->Return(hRes);
  4114. }
  4115. CReleaseMe _1(pProv);
  4116. // Set up the sink chain to be delivered to the provider.
  4117. // The code & destruct sequence is critical and the
  4118. // refcounting is very carefully thought out. Do not
  4119. // change this code unless you know exactly what you are
  4120. // doing. And don't even change it then.
  4121. // ======================================================
  4122. CProviderSink *pProvSink = new CProviderSink(1, Query);
  4123. if (pProvSink == 0)
  4124. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  4125. CReleaseMe _3(pProvSink);
  4126. CDecoratingSink * pDecore = new CDecoratingSink(pSink, this);
  4127. if (pDecore == NULL)
  4128. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  4129. pProvSink->SetNextSink(pDecore);
  4130. // Before calling the provider, map the provider to the
  4131. // task so that we can cancel it proactively, if required.
  4132. // =======================================================
  4133. hRes = ((CWmiArbitrator *) m_pArb)->MapProviderToTask(0, pCtx, pProv, pProvSink);
  4134. if (FAILED(hRes))
  4135. return pSink->Return(hRes);
  4136. // Now tell the provider to start enumerating.
  4137. hRes = pProv->ExecQueryAsync(QueryFormat,
  4138. Query, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  4139. pCtx, pProvSink);
  4140. return hRes;
  4141. }
  4142. //***************************************************************************
  4143. //
  4144. // CWbemNamespace::DynAux_ExecQueryAsync
  4145. //
  4146. // Executes a SQL-1 query against a dynamic instance provider for the class
  4147. // in the query.
  4148. //
  4149. // PARAMETERS:
  4150. //
  4151. // IN DWORD dwNamespace Namespace handle to the current
  4152. // namespace (see objdb.h)
  4153. // IN CWbemObject* pClassDef Class definition of the class in the
  4154. // query. Must be dynamic.
  4155. // IN LPWSTR Query The query string.
  4156. // IN LPWSTR QueryFormat The query language. Must be WQL.
  4157. // IN long lFlags The flags. Not used.
  4158. // OUT CFlexArray &aInstances Destinatino for the instances found.
  4159. // OUT IWbemClassObject** ppErrorObj Destination for the error object. IF
  4160. // not NULL, an error object may be placed
  4161. // here. In this case, it is the caller's
  4162. // responsibility to release it.
  4163. // RETURN VALUES:
  4164. //
  4165. // WBEM_S_NO_ERROR Success (even though there may not be
  4166. // any instances).
  4167. // WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
  4168. // class is incomplete.
  4169. // WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
  4170. // registered with us or with COM.
  4171. // WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
  4172. // instances.
  4173. // WBEM_E_FAILED Unexpected error has occured.
  4174. //
  4175. //***************************************************************************
  4176. HRESULT CWbemNamespace::DynAux_ExecQueryExtendedAsync(
  4177. LPWSTR wsProvider,
  4178. LPWSTR Query,
  4179. LPWSTR QueryFormat,
  4180. long lFlags,
  4181. IWbemContext* pCtx,
  4182. CComplexProjectionSink* pSink
  4183. )
  4184. {
  4185. COperationError OpInfo(pSink, L"ExecQuery", Query, FALSE);
  4186. if ( !OpInfo.IsOk() ) return WBEM_E_OUT_OF_MEMORY;
  4187. // Access the provider cache.
  4188. // ==========================
  4189. IWbemServices *pProv = 0;
  4190. HRESULT hRes;
  4191. if(m_pProvFact == NULL)
  4192. hRes = WBEM_E_CRITICAL_ERROR;
  4193. else
  4194. {
  4195. WmiInternalContext t_InternalContext ;
  4196. ZeroMemory ( & t_InternalContext , sizeof ( t_InternalContext ) ) ; // SEC:REVIEWED 2002-03-22 : OK
  4197. hRes = m_pProvFact->GetProvider(
  4198. t_InternalContext ,
  4199. 0, // lFlags
  4200. pCtx,
  4201. 0,
  4202. m_wszUserName,
  4203. m_wsLocale,
  4204. 0, // IWbemPath pointer
  4205. wsProvider, // provider name
  4206. IID_IWbemServices,
  4207. (LPVOID *) &pProv
  4208. );
  4209. }
  4210. if (FAILED(hRes))
  4211. {
  4212. return pSink->Return(hRes);
  4213. }
  4214. CReleaseMe _(pProv);
  4215. _IWmiProviderConfiguration *t_Configuration = NULL ;
  4216. hRes = pProv->QueryInterface ( IID__IWmiProviderConfiguration , ( void ** ) & t_Configuration ) ;
  4217. if ( SUCCEEDED ( hRes ) )
  4218. {
  4219. CReleaseMe _1(t_Configuration);
  4220. VARIANT t_Variant ;
  4221. VariantInit ( & t_Variant ) ;
  4222. hRes = t_Configuration->Query (
  4223. this ,
  4224. lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS ,
  4225. pCtx ,
  4226. WBEM_PROVIDER_CONFIGURATION_CLASS_ID_INSTANCE_PROVIDER_REGISTRATION ,
  4227. WBEM_PROVIDER_CONFIGURATION_PROPERTY_ID_EXTENDEDQUERY_SUPPORT ,
  4228. & t_Variant
  4229. ) ;
  4230. if ( SUCCEEDED ( hRes ) )
  4231. {
  4232. if ( t_Variant.boolVal == VARIANT_TRUE )
  4233. {
  4234. CDecoratingSink * pDecore = new CDecoratingSink(pSink, this);
  4235. if(pDecore == NULL)
  4236. return pSink->Return(WBEM_E_OUT_OF_MEMORY);
  4237. pDecore->AddRef();
  4238. CReleaseMe cdecor(pDecore);
  4239. hRes = pProv->ExecQueryAsync(QueryFormat, Query, lFlags& ~WBEM_FLAG_USE_AMENDED_QUALIFIERS, pCtx, pDecore);
  4240. }
  4241. else
  4242. {
  4243. hRes = WBEM_E_INVALID_QUERY ;
  4244. }
  4245. VariantClear ( & t_Variant ) ;
  4246. }
  4247. else
  4248. {
  4249. hRes = WBEM_E_UNEXPECTED ;
  4250. }
  4251. }
  4252. else
  4253. {
  4254. hRes = WBEM_E_UNEXPECTED ;
  4255. }
  4256. return hRes;
  4257. }
  4258. //***************************************************************************
  4259. //
  4260. // CWbemNamespace::Static_QueryRepository
  4261. //
  4262. // Performs query against the repository. This only happens if there is an
  4263. // associated task. If not, then we execute the query on the same thread.
  4264. //
  4265. // PARAMETERS:
  4266. //
  4267. // READONLY CWbemObject *pClassDef The definition of the class to retrieve
  4268. // instances of.
  4269. // long lFlags The flags (deep/shallow)
  4270. //
  4271. // RETURN VALUES:
  4272. //
  4273. // WBEM_NO_ERROR No errors. This includes a no-error situation
  4274. // with zero instances returned.
  4275. // WBEM_E_INVALID_PROVIDE_REGISTRATION Provider registration for this
  4276. // class is incomplete.
  4277. // WBEM_E_PROVIDER_NOT_FOUND Provider could not be located. It is not
  4278. // registered with us or with COM.
  4279. // WBEM_E_PROVIDER_NOT_CAPABLE Provider is not capable of enumerating
  4280. // instances.
  4281. // WBEM_E_FAILED Unexpected error has occured.
  4282. //
  4283. //***************************************************************************
  4284. HRESULT CWbemNamespace::Static_QueryRepository(
  4285. READONLY CWbemObject *pClassDef,
  4286. long lFlags,
  4287. IWbemContext* pCtx,
  4288. CBasicObjectSink* pSink ,
  4289. QL_LEVEL_1_RPN_EXPRESSION* pParsedQuery,
  4290. LPCWSTR pwszClassName,
  4291. CWmiMerger* pWmiMerger
  4292. )
  4293. {
  4294. HRESULT hr = WBEM_S_NO_ERROR;
  4295. // First, get the current task and request. If there isn't one, we're most
  4296. // likely being called on an ESS callback, and will just perform the call on
  4297. // this thread.
  4298. CWbemRequest* pCurrReq = CWbemQueue::GetCurrentRequest();
  4299. if ( NULL != pCurrReq && NULL != pCurrReq->m_phTask &&
  4300. ConfigMgr::GetEnableQueryArbitration() )
  4301. {
  4302. // We'll need the finalizer in case we need to cancel something
  4303. _IWmiFinalizer* pMainFnz = NULL;
  4304. HRESULT hr = ((CWmiTask*) pCurrReq->m_phTask)->GetFinalizer( &pMainFnz );
  4305. CReleaseMe rm( pMainFnz );
  4306. if ( SUCCEEDED( hr ) )
  4307. {
  4308. //
  4309. // creates the CMergerDynReq_Static_GetInstances
  4310. // creates the Merger Request Manager
  4311. // adds the request to the Request Manager
  4312. //
  4313. hr = pWmiMerger->RegisterArbitratedStaticRequest( pClassDef, lFlags, pCtx, pSink, this, pParsedQuery );
  4314. if (FAILED(hr))
  4315. {
  4316. pMainFnz->CancelTask ( 0 );
  4317. }
  4318. } // IF Got Finalizer
  4319. // In the case of an error we should do a setstatus of the error. Otherwise, the setstatus will occur
  4320. // when the new request is processed.
  4321. if ( FAILED( hr ) )
  4322. {
  4323. pSink->SetStatus( 0L, hr, 0L, NULL );
  4324. }
  4325. }
  4326. else
  4327. {
  4328. // If we're here, then we should disallow merger specific throttling since
  4329. // this request is happening through an internal thread without following
  4330. // the request/task hierarchy, meaning that there shouldn't be a hierarchy
  4331. // we need to worry about for this class, so don't let the merger do any
  4332. // internal throttling
  4333. pWmiMerger->EnableMergerThrottling( false );
  4334. int nRes = CQueryEngine::ExecAtomicDbQuery(
  4335. GetNsSession(),
  4336. GetNsHandle(),
  4337. GetScope(),
  4338. pwszClassName,
  4339. pParsedQuery,
  4340. pSink,
  4341. this );
  4342. if (nRes == CQueryEngine::invalid_query)
  4343. hr = WBEM_E_INVALID_QUERY;
  4344. else if(nRes != 0)
  4345. hr = WBEM_E_FAILED;
  4346. else
  4347. hr = WBEM_S_NO_ERROR;
  4348. pSink->SetStatus( 0L, hr, 0L, NULL );
  4349. }
  4350. return hr;
  4351. }
  4352. //***************************************************************************
  4353. //
  4354. // CWbemNamespace::DecorateObject
  4355. //
  4356. // Sets the origin information on a given object to reflect this namespace
  4357. // and this server. See CWbemObject::Decorate in fastobj.h for details.
  4358. // THIS FUNCTION CAN ONLY DECORATE CWbemObject POINTERS, NOT OTHER PEOPLE'S
  4359. // IMPLEMENTATIONS of IWbemClassObject.
  4360. //
  4361. // PARAMETERS:
  4362. //
  4363. // IWbemClassObject* pObject The object to decorate.
  4364. //
  4365. // RETURN VALUES:
  4366. //
  4367. // WBEM_S_NO_ERROR Success
  4368. // WBEM_E_INVALID_PARAMETER pObject == NULL.
  4369. //
  4370. //***************************************************************************
  4371. HRESULT CWbemNamespace::DecorateObject(IWbemClassObject* pObject)
  4372. {
  4373. if(pObject == NULL)
  4374. return WBEM_E_INVALID_PARAMETER;
  4375. return ((CWbemObject*)pObject)->Decorate(ConfigMgr::GetMachineName(),
  4376. m_pThisNamespace);
  4377. }
  4378. //***************************************************************************
  4379. //
  4380. //***************************************************************************
  4381. typedef std::vector<CDynasty*, wbem_allocator<CDynasty*> > CDynastyPtrArray;
  4382. typedef std::map<LPWSTR, CDynasty*, wcsiless, wbem_allocator<CDynasty*> > CCDynastyMap;
  4383. HRESULT AddAllMembers(CDynasty* pDynasty, CCDynastyMap& Map)
  4384. {
  4385. // Catch any exceptions the allocator might throw
  4386. try
  4387. {
  4388. Map[pDynasty->m_wszClassName] = pDynasty;
  4389. }
  4390. catch(CX_MemoryException &)
  4391. {
  4392. return WBEM_E_OUT_OF_MEMORY;
  4393. }
  4394. HRESULT hr = WBEM_S_NO_ERROR;
  4395. CFlexArray* pChildren = &pDynasty->m_Children;
  4396. for(int i = 0; SUCCEEDED(hr) && i < pChildren->Size(); i++)
  4397. {
  4398. hr = AddAllMembers((CDynasty*)pChildren->GetAt(i), Map);
  4399. }
  4400. return hr;
  4401. }
  4402. //***************************************************************************
  4403. //
  4404. // CWbemNamespace::DynAux_BuildClassHierarchy
  4405. //
  4406. // Recursively builds the hierarchy of classes derived from a given one.
  4407. // The structure used to represent the hierarchy -- CDynasty is described
  4408. // in objdb.h
  4409. //
  4410. // PARAMETERS:
  4411. //
  4412. // IN LPWSTR wszClassName The name of the parent class.
  4413. // IN LONG lFlags If SHALLOW, just the class itself is
  4414. // returned. If DEEP, recursive enumeration
  4415. // is performed.
  4416. // OUT CDynasty** ppDynasty Destination for the tree. The caller must
  4417. // delete the pointer on success.
  4418. //
  4419. // RETURN VALUES:
  4420. //
  4421. // WBEM_S_NO_ERROR Success
  4422. // Any of the return values returned by GetObject or CreateClassEnum,
  4423. // as documented in the help file.
  4424. //
  4425. //***************************************************************************
  4426. HRESULT CWbemNamespace::DynAux_BuildClassHierarchy(
  4427. IN LPWSTR wszClassName,
  4428. IN LONG lFlags,
  4429. IN IWbemContext* pCtx,
  4430. OUT wmilib::auto_ptr<CDynasty> & pDynasty,
  4431. OUT IWbemClassObject** ppErrorObj)
  4432. {
  4433. HRESULT hres;
  4434. *ppErrorObj = NULL;
  4435. // Get the list of classes from all class providers
  4436. // ================================================
  4437. CSynchronousSink* pSyncSink = CSynchronousSink::Create();
  4438. if(pSyncSink == NULL) return WBEM_E_OUT_OF_MEMORY;
  4439. pSyncSink->AddRef();
  4440. CReleaseMe rm1(pSyncSink);
  4441. hres = Exec_CreateClassEnum(wszClassName,
  4442. lFlags | WBEM_FLAG_NO_STATIC,
  4443. pCtx,
  4444. pSyncSink);
  4445. pSyncSink->Block();
  4446. pSyncSink->GetStatus(&hres, NULL, ppErrorObj);
  4447. if(FAILED(hres))
  4448. return hres;
  4449. // Get the static dynasty
  4450. // ======================
  4451. wmilib::auto_ptr<CDynasty> pMainDynasty;
  4452. HRESULT hRes = CRepository::BuildClassHierarchy(m_pSession,
  4453. m_pNsHandle,
  4454. wszClassName,
  4455. lFlags & WBEM_MASK_DEPTH,
  4456. pMainDynasty);
  4457. if (hRes == WBEM_E_NOT_FOUND)
  4458. {
  4459. IWbemClassObject* pObj;
  4460. HRESULT hres = Exec_GetObjectByPath(wszClassName, lFlags, pCtx,
  4461. &pObj,
  4462. ppErrorObj);
  4463. if(FAILED(hres)) return hres;
  4464. CReleaseMe rmClassObj(pObj);
  4465. pMainDynasty.reset(CDynasty::Create(pObj));
  4466. if(NULL == pMainDynasty.get()) return WBEM_E_OUT_OF_MEMORY;
  4467. if(pMainDynasty->m_pClassObj == NULL)
  4468. {
  4469. ERRORTRACE((LOG_WBEMCORE, "Provider returned invalid class for %S\n",wszClassName));
  4470. return WBEM_E_PROVIDER_FAILURE;
  4471. }
  4472. hRes = S_OK;
  4473. }
  4474. if (FAILED(hRes)) return hRes;
  4475. CRefedPointerArray<IWbemClassObject> &rProvidedClasses = pSyncSink->GetObjects();
  4476. // Create a map of class names to their dynasties
  4477. // ==============================================
  4478. CCDynastyMap mapClasses;
  4479. hres = AddAllMembers(pMainDynasty.get(), mapClasses);
  4480. if ( FAILED(hres)) return hres;
  4481. CDynastyPtrArray aProvidedDyns;
  4482. try
  4483. {
  4484. aProvidedDyns.reserve(rProvidedClasses.GetSize());
  4485. }
  4486. catch(CX_MemoryException &)
  4487. {
  4488. return WBEM_E_OUT_OF_MEMORY;
  4489. }
  4490. for(int i = 0; i < rProvidedClasses.GetSize(); i++)
  4491. {
  4492. CDynasty* pNew = CDynasty::Create(rProvidedClasses[i]);
  4493. if(pNew == NULL)
  4494. return WBEM_E_OUT_OF_MEMORY;
  4495. if(pNew->m_pClassObj == NULL)
  4496. {
  4497. delete pNew;
  4498. ERRORTRACE((LOG_WBEMCORE, "Provider returned invalid class!\n"));
  4499. continue;
  4500. }
  4501. // The vector or the map may throw exceptions
  4502. try
  4503. {
  4504. mapClasses[pNew->m_wszClassName] = pNew;
  4505. aProvidedDyns.push_back(pNew);
  4506. }
  4507. catch(CX_MemoryException &)
  4508. {
  4509. return WBEM_E_OUT_OF_MEMORY;
  4510. }
  4511. }
  4512. // Go through it once and add all classes to their parent's dynasty
  4513. // ================================================================
  4514. for(CDynastyPtrArray::iterator it = aProvidedDyns.begin();
  4515. it != aProvidedDyns.end(); it++)
  4516. {
  4517. CDynasty* pDyn = *it;
  4518. CVar vParent;
  4519. CWbemObject *pObj = (CWbemObject *) pDyn->m_pClassObj;
  4520. if(FAILED(pObj->GetSuperclassName(&vParent)) ||
  4521. vParent.IsNull())
  4522. {
  4523. ERRORTRACE((LOG_WBEMCORE,"Provider returned top-level class %S as a child "
  4524. "of %S\n", pDyn->m_wszClassName, wszClassName));
  4525. continue;
  4526. }
  4527. CCDynastyMap::iterator itParent =
  4528. mapClasses.find(vParent.GetLPWSTR());
  4529. if((itParent == mapClasses.end()))
  4530. {
  4531. if(wbem_wcsicmp(pDyn->m_wszClassName, wszClassName))
  4532. {
  4533. ERRORTRACE((LOG_WBEMCORE,"Provider returned class %S without parent!\n",
  4534. vParent.GetLPWSTR()));
  4535. }
  4536. continue;
  4537. }
  4538. CDynasty* pParentDyn = itParent->second;
  4539. pParentDyn->AddChild(pDyn);
  4540. }
  4541. // Build the chain up to the highest keyed parent
  4542. // ==============================================
  4543. pDynasty = pMainDynasty;
  4544. hres = DynAux_BuildChainUp( pCtx, pDynasty, ppErrorObj);
  4545. return hres;
  4546. }
  4547. //***************************************************************************
  4548. //
  4549. //***************************************************************************
  4550. HRESULT CWbemNamespace::DynAux_BuildChainUp( IN IWbemContext* pCtx,
  4551. OUT wmilib::auto_ptr<CDynasty> & pTop,
  4552. OUT IWbemClassObject** ppErrorObj)
  4553. {
  4554. *ppErrorObj = NULL;
  4555. // Go up while there is a key at this level and we are dynamic
  4556. // ===========================================================
  4557. while( pTop->IsDynamic() && pTop->IsKeyed())
  4558. {
  4559. CVar vParentName;
  4560. CWbemObject *pObj = (CWbemObject *) pTop->m_pClassObj;
  4561. if(FAILED(pObj->GetSuperclassName(&vParentName)) ||
  4562. vParentName.IsNull())
  4563. {
  4564. // Top level --- time to quit
  4565. // ==========================
  4566. return WBEM_S_NO_ERROR;
  4567. }
  4568. IWbemClassObject* pParent;
  4569. HRESULT hres = Exec_GetObjectByPath(vParentName.GetLPWSTR(), 0,pCtx,&pParent, ppErrorObj);
  4570. if(FAILED(hres))
  4571. return hres;
  4572. if(pParent == NULL)
  4573. return WBEM_E_PROVIDER_FAILURE;
  4574. // SJS - Amendment is the same as Abstract
  4575. if(!((CWbemClass*)pParent)->IsKeyed() ||
  4576. ((CWbemClass*)pParent)->IsAbstract() ||
  4577. ((CWbemClass*)pParent)->IsAmendment() )
  4578. {
  4579. // We are it
  4580. // =========
  4581. pParent->Release();
  4582. return WBEM_S_NO_ERROR;
  4583. }
  4584. // Extend the dynasty by this class
  4585. // ================================
  4586. wmilib::auto_ptr<CDynasty> pNew( CDynasty::Create(pParent));
  4587. if (NULL == pNew.get()) return WBEM_E_OUT_OF_MEMORY;
  4588. pParent->Release();
  4589. if(pNew->m_pClassObj == NULL)
  4590. {
  4591. return WBEM_E_PROVIDER_FAILURE;
  4592. }
  4593. pNew->AddChild(pTop.get());
  4594. pTop.release();
  4595. pTop.reset(pNew.release());
  4596. }
  4597. return WBEM_S_NO_ERROR;
  4598. }
  4599. //***************************************************************************
  4600. //
  4601. //***************************************************************************
  4602. HRESULT CWbemNamespace::IsPutRequiredForClass(CWbemClass* pClass,
  4603. CWbemInstance* pInst, IWbemContext* pCtx,
  4604. BOOL bParentTakenCareOf)
  4605. {
  4606. HRESULT hres;
  4607. // Get the per-property put information out of the context
  4608. // =======================================================
  4609. BOOL bRestrictedPut = FALSE;
  4610. BOOL bStrictNulls = FALSE;
  4611. BOOL bPropertyList = FALSE;
  4612. CWStringArray awsProperties;
  4613. hres = GetContextPutExtensions(pCtx, bRestrictedPut, bStrictNulls,
  4614. bPropertyList, awsProperties);
  4615. if(FAILED(hres))
  4616. return hres;
  4617. if(bRestrictedPut && bStrictNulls && !bPropertyList)
  4618. {
  4619. // All properties must be put, even the NULL ones
  4620. // ==============================================
  4621. return WBEM_S_NO_ERROR;
  4622. }
  4623. // Enumerate all properties of the class
  4624. // =====================================
  4625. long lEnumFlags = 0;
  4626. if(bParentTakenCareOf)
  4627. {
  4628. // Only look at local (non-propagated) properties
  4629. // ==============================================
  4630. lEnumFlags = WBEM_FLAG_LOCAL_ONLY;
  4631. }
  4632. else
  4633. {
  4634. // We are in charge of our parent's properties
  4635. // ===========================================
  4636. lEnumFlags = WBEM_FLAG_NONSYSTEM_ONLY;
  4637. }
  4638. pClass->BeginEnumeration(lEnumFlags);
  4639. BSTR strName = NULL;
  4640. while((hres = pClass->Next(0, &strName, NULL, NULL, NULL)) == S_OK)
  4641. {
  4642. hres = DoesNeedToBePut(strName, pInst, bRestrictedPut,
  4643. bStrictNulls, bPropertyList, awsProperties);
  4644. SysFreeString(strName);
  4645. if(hres == WBEM_S_NO_ERROR)
  4646. {
  4647. // Found a needed property
  4648. // =======================
  4649. return WBEM_S_NO_ERROR;
  4650. }
  4651. if(FAILED(hres))
  4652. return hres;
  4653. }
  4654. // No properties of this class need to be put
  4655. // ==========================================
  4656. return WBEM_S_FALSE;
  4657. }
  4658. //***************************************************************************
  4659. //
  4660. //***************************************************************************
  4661. HRESULT CWbemNamespace::DoesNeedToBePut(LPCWSTR wszName, CWbemInstance* pInst,
  4662. BOOL bRestrictedPut, BOOL bStrictNulls, BOOL bPropertyList,
  4663. CWStringArray& awsProperties)
  4664. {
  4665. HRESULT hres;
  4666. // Check if the property is a key
  4667. // ==============================
  4668. CVar vKey;
  4669. pInst->GetPropQualifier((LPWSTR)wszName, L"key", &vKey);
  4670. if(vKey.GetType() == VT_BOOL && vKey.GetBool())
  4671. {
  4672. // It's a key --- no such thing as updating its value, and this code
  4673. // only applies to updates.
  4674. // =================================================================
  4675. return WBEM_S_FALSE;
  4676. }
  4677. // Determine if NULLness and or membership in the list play any role
  4678. // =================================================================
  4679. BOOL bCheckNullness = FALSE;
  4680. BOOL bCheckMembership = FALSE;
  4681. if(bRestrictedPut)
  4682. {
  4683. bCheckNullness = !bStrictNulls;
  4684. bCheckMembership = bPropertyList;
  4685. }
  4686. else
  4687. {
  4688. bCheckNullness = TRUE;
  4689. bCheckMembership = FALSE;
  4690. }
  4691. // Check NULLness and/or membership if required
  4692. // ============================================
  4693. BOOL bNullnessChecked = FALSE;
  4694. BOOL bMembershipChecked = FALSE;
  4695. if(bCheckNullness)
  4696. {
  4697. CVar vVal;
  4698. hres = pInst->GetNonsystemPropertyValue((LPWSTR)wszName, &vVal);
  4699. if(FAILED(hres))
  4700. return hres;
  4701. bNullnessChecked = !vVal.IsNull();
  4702. }
  4703. else
  4704. bNullnessChecked = TRUE;
  4705. if(bCheckMembership)
  4706. {
  4707. int nIndex = awsProperties.FindStr(wszName, CWStringArray::no_case);
  4708. bMembershipChecked = (nIndex >= 0);
  4709. }
  4710. else
  4711. bMembershipChecked = TRUE;
  4712. // Make sure that both NULLness and membership either checked out or were
  4713. // not required
  4714. // ======================================================================
  4715. if(bMembershipChecked && bNullnessChecked)
  4716. {
  4717. return WBEM_S_NO_ERROR;
  4718. }
  4719. else
  4720. {
  4721. return WBEM_S_FALSE;
  4722. }
  4723. }
  4724. //***************************************************************************
  4725. //
  4726. //***************************************************************************
  4727. HRESULT CWbemNamespace::GetContextPutExtensions(IWbemContext* pCtx,
  4728. BOOL& bRestrictedPut, BOOL& bStrictNulls, BOOL& bPropertyList,
  4729. CWStringArray& awsProperties)
  4730. {
  4731. HRESULT hres;
  4732. if(pCtx == NULL)
  4733. {
  4734. //
  4735. // Default is: no restructions, which makes the rest of the properties
  4736. // irrelevant
  4737. //
  4738. bRestrictedPut = FALSE;
  4739. return WBEM_S_NO_ERROR;
  4740. }
  4741. // Initialize out-params
  4742. // =====================
  4743. bRestrictedPut = FALSE;
  4744. bStrictNulls = FALSE;
  4745. bPropertyList = FALSE;
  4746. awsProperties.Empty();
  4747. // Check if the context is even present
  4748. // ====================================
  4749. if(pCtx == NULL)
  4750. return WBEM_S_NO_ERROR;
  4751. // Check if put extensions are specified
  4752. // =====================================
  4753. hres = GetContextBoolean(pCtx, L"__PUT_EXTENSIONS", &bRestrictedPut);
  4754. if(FAILED(hres)) return hres;
  4755. if(!bRestrictedPut)
  4756. return WBEM_S_NO_ERROR;
  4757. // Check if NULLs are strict
  4758. // =========================
  4759. hres = GetContextBoolean(pCtx, L"__PUT_EXT_STRICT_NULLS",
  4760. &bStrictNulls);
  4761. if(FAILED(hres)) return hres;
  4762. // Check if the list of properties is available
  4763. // ============================================
  4764. VARIANT v;
  4765. VariantInit(&v);
  4766. CClearMe cm1(&v);
  4767. hres = pCtx->GetValue(L"__PUT_EXT_PROPERTIES", 0, &v);
  4768. if(FAILED(hres))
  4769. {
  4770. if(hres == WBEM_E_NOT_FOUND)
  4771. {
  4772. return WBEM_S_NO_ERROR;
  4773. }
  4774. else
  4775. {
  4776. ERRORTRACE((LOG_WBEMCORE, "Error retrieving list of properties "
  4777. "from context: %X\n", hres));
  4778. return hres;
  4779. }
  4780. }
  4781. if(V_VT(&v) != (VT_BSTR | VT_ARRAY))
  4782. {
  4783. ERRORTRACE((LOG_WBEMCORE, "Invalid type is used for "
  4784. "the list of properties in the context: must be "
  4785. "string array. The value will be ignored\n"));
  4786. return WBEM_S_NO_ERROR;
  4787. }
  4788. bPropertyList = TRUE;
  4789. // Transfer property names to the array
  4790. // ====================================
  4791. CSafeArray saProperties(V_ARRAY(&v), VT_BSTR,
  4792. CSafeArray::no_delete | CSafeArray::bind);
  4793. for(int i = 0; i < saProperties.Size(); i++)
  4794. {
  4795. BSTR strProp = saProperties.GetBSTRAt(i);
  4796. CSysFreeMe sfm(strProp);
  4797. if (strProp)
  4798. {
  4799. if (CFlexArray::no_error != awsProperties.Add(strProp))
  4800. return WBEM_E_OUT_OF_MEMORY;
  4801. }
  4802. }
  4803. return WBEM_S_NO_ERROR;
  4804. }
  4805. //***************************************************************************
  4806. //
  4807. //***************************************************************************
  4808. HRESULT CWbemNamespace::GetContextBoolean(IWbemContext* pCtx,
  4809. LPCWSTR wszName, BOOL* pbValue)
  4810. {
  4811. HRESULT hres;
  4812. *pbValue = FALSE;
  4813. //
  4814. // NULL context means "FALSE"
  4815. //
  4816. if(pCtx == NULL)
  4817. return WBEM_S_NO_ERROR;
  4818. VARIANT v;
  4819. VariantInit(&v);
  4820. CClearMe cm1(&v);
  4821. hres = pCtx->GetValue((LPWSTR)wszName, 0, &v);
  4822. if(FAILED(hres))
  4823. {
  4824. if(hres == WBEM_E_NOT_FOUND)
  4825. {
  4826. return WBEM_S_NO_ERROR;
  4827. }
  4828. else
  4829. {
  4830. ERRORTRACE((LOG_WBEMCORE, "Error retrieving context property %S:"
  4831. " %X\n", wszName, hres));
  4832. return hres;
  4833. }
  4834. }
  4835. if(V_VT(&v) != VT_BOOL)
  4836. {
  4837. ERRORTRACE((LOG_WBEMCORE, "Invalid type is used for "
  4838. "%S property of the context: must be "
  4839. "boolean. The value will be ignored\n", wszName));
  4840. return WBEM_S_NO_ERROR;
  4841. }
  4842. if(V_BOOL(&v) != VARIANT_TRUE)
  4843. {
  4844. return WBEM_S_NO_ERROR;
  4845. }
  4846. *pbValue = TRUE;
  4847. return WBEM_S_NO_ERROR;
  4848. }
  4849. //***************************************************************************
  4850. //
  4851. //***************************************************************************
  4852. STDMETHODIMP CWbemNamespace::FindKeyRoot(LPCWSTR wszClassName,
  4853. IWbemClassObject** ppKeyRootClass)
  4854. {
  4855. //
  4856. // Check if the namespace is still valid (returns if not)
  4857. //
  4858. HRESULT hRes = CheckNs();
  4859. if (FAILED(hRes))
  4860. return hRes;
  4861. //
  4862. // Call on the database to do the job
  4863. //
  4864. hRes = CRepository::FindKeyRoot(m_pSession, m_pNsHandle, wszClassName, ppKeyRootClass);
  4865. return hRes;
  4866. }
  4867. //***************************************************************************
  4868. //
  4869. //***************************************************************************
  4870. STDMETHODIMP CWbemNamespace::GetNormalizedPath( BSTR pstrPath,
  4871. BSTR* pstrStandardPath )
  4872. {
  4873. //
  4874. // Check if the namespace is still valid (returns if not)
  4875. //
  4876. HRESULT hRes = CheckNs();
  4877. if (FAILED(hRes))
  4878. return hRes;
  4879. //
  4880. // check parameters.
  4881. //
  4882. if ( NULL == pstrPath || NULL == pstrStandardPath )
  4883. {
  4884. return WBEM_E_INVALID_PARAMETER;
  4885. }
  4886. HRESULT hres;
  4887. *pstrStandardPath = NULL;
  4888. // Parse it
  4889. // ========
  4890. CObjectPathParser Parser;
  4891. ParsedObjectPath* pPath;
  4892. int nRes = Parser.Parse(pstrPath, &pPath);
  4893. if( nRes != CObjectPathParser::NoError )
  4894. {
  4895. return WBEM_E_INVALID_OBJECT_PATH;
  4896. }
  4897. CDeleteMe<ParsedObjectPath> dm(pPath);
  4898. //
  4899. // Figure out the class that defined the key
  4900. //
  4901. IWbemClassObject* pKeyRootClass = NULL;
  4902. hres = FindKeyRoot(pPath->m_pClass, &pKeyRootClass);
  4903. if(FAILED(hres))
  4904. {
  4905. return hres;
  4906. }
  4907. CReleaseMe rm(pKeyRootClass);
  4908. _IWmiObject* pWmiObject = NULL;
  4909. hres = pKeyRootClass->QueryInterface(IID__IWmiObject, (void**)&pWmiObject);
  4910. if(FAILED(hres))
  4911. {
  4912. return hres;
  4913. }
  4914. CReleaseMe rm1(pWmiObject);
  4915. long lHandle = 0L;
  4916. ULONG uFlags = 0L;
  4917. WCHAR wszClassName[64];
  4918. DWORD dwBuffSize = 64;
  4919. DWORD dwBuffUsed = 0;
  4920. BOOL fNull = FALSE;
  4921. LPWSTR pwszName = wszClassName;
  4922. LPWSTR pwszDelete = NULL;
  4923. // Try to read in the class name. Allocate a buffer if we have to.
  4924. hres = pWmiObject->ReadProp( L"__CLASS", 0L, dwBuffSize, NULL, NULL, &fNull, &dwBuffUsed, pwszName );
  4925. if ( FAILED( hres ) )
  4926. {
  4927. if ( WBEM_E_BUFFER_TOO_SMALL == hres )
  4928. {
  4929. pwszName = new WCHAR[dwBuffUsed/2];
  4930. if ( NULL == pwszName )
  4931. {
  4932. return WBEM_E_OUT_OF_MEMORY;
  4933. }
  4934. else
  4935. {
  4936. dwBuffSize = dwBuffUsed;
  4937. // Try to read in the class name. Allocate a buffer if we have to.
  4938. hres = pWmiObject->ReadProp( L"__CLASS", 0L, dwBuffSize, NULL, NULL, &fNull, &dwBuffUsed, pwszName );
  4939. if ( FAILED( hres ) )
  4940. {
  4941. delete [] pwszName;
  4942. return hres;
  4943. }
  4944. // Allows for scoped cleanup only if we alloctaed something
  4945. pwszDelete = pwszName;
  4946. }
  4947. }
  4948. else
  4949. {
  4950. return hres;
  4951. }
  4952. }
  4953. //
  4954. // Ensures proper cleanup. If we didn't allocate a buffer to delete,
  4955. // this pointer will be NULL.
  4956. //
  4957. CVectorDeleteMe<WCHAR> vdm1(pwszDelete);
  4958. // oop
  4959. if ( fNull )
  4960. {
  4961. return WBEM_E_INVALID_OPERATION;
  4962. }
  4963. //
  4964. // want to normalize out the single key prop exception
  4965. //
  4966. if ( pPath->m_dwNumKeys == 1 )
  4967. {
  4968. delete pPath->m_paKeys[0]->m_pName;
  4969. pPath->m_paKeys[0]->m_pName = NULL;
  4970. }
  4971. //
  4972. // set the normalized class on the path if different
  4973. // than the one in the path.
  4974. //
  4975. if ( wbem_wcsicmp( pPath->m_pClass, pwszName ) != 0 )
  4976. {
  4977. if ( !pPath->SetClassName( pwszName ) )
  4978. {
  4979. return WBEM_E_OUT_OF_MEMORY;
  4980. }
  4981. }
  4982. //
  4983. // now unparse the normalized path
  4984. //
  4985. LPWSTR wszNormPath;
  4986. nRes = CObjectPathParser::Unparse( pPath, &wszNormPath );
  4987. if ( nRes != CObjectPathParser::NoError )
  4988. {
  4989. return WBEM_E_OUT_OF_MEMORY;
  4990. }
  4991. *pstrStandardPath = SysAllocString( wszNormPath );
  4992. delete wszNormPath;
  4993. return *pstrStandardPath != NULL ? WBEM_S_NO_ERROR : WBEM_E_OUT_OF_MEMORY;
  4994. }
  4995. class CRevertCallSec
  4996. {
  4997. BOOL m_bEnabled;
  4998. IUnknown * m_pCallSec;
  4999. public:
  5000. CRevertCallSec(BOOL bEnabled,IUnknown * pCallSec):
  5001. m_bEnabled(bEnabled),
  5002. m_pCallSec(pCallSec){};
  5003. ~CRevertCallSec(){
  5004. if (m_bEnabled){
  5005. IUnknown * pOld = NULL;
  5006. CoSwitchCallContext(m_pCallSec,&pOld);
  5007. }
  5008. };
  5009. };
  5010. //***************************************************************************
  5011. //
  5012. //***************************************************************************
  5013. STDMETHODIMP CWbemNamespace::InternalGetClass(
  5014. LPCWSTR wszClassName,
  5015. IWbemClassObject** ppClass)
  5016. {
  5017. if (g_bDontAllowNewConnections || m_bShutDown)
  5018. {
  5019. return WBEM_E_SHUTTING_DOWN;
  5020. }
  5021. IWbemContext *pContext = NULL ;
  5022. CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ;
  5023. if (pReq == NULL)
  5024. {
  5025. pContext = ConfigMgr::GetNewContext();
  5026. if ( pContext == NULL )
  5027. return WBEM_E_OUT_OF_MEMORY;
  5028. }
  5029. else
  5030. {
  5031. pContext = pReq->GetContext();
  5032. pContext->AddRef () ; //for CReleaseMe
  5033. }
  5034. CReleaseMe _1_pContext (pContext) ;
  5035. HRESULT hr;
  5036. // determine if there is a call context. If there is, then we
  5037. // dont do anything.
  5038. IServerSecurity * pSec = NULL;
  5039. IWbemCallSecurity * pCallSec = NULL;
  5040. IUnknown * pOld = NULL, *pNew = NULL;
  5041. hr = CoGetCallContext(IID_IServerSecurity, (void**)&pSec);
  5042. if(SUCCEEDED(hr))
  5043. {
  5044. pSec->Release();
  5045. }
  5046. else
  5047. {
  5048. // provider subsystem needs a call context, so create on
  5049. pCallSec = CWbemCallSecurity::CreateInst();
  5050. if(pCallSec == NULL)
  5051. return WBEM_E_OUT_OF_MEMORY;
  5052. }
  5053. CReleaseMe rm(pCallSec);
  5054. // initialize call security for provider sub system
  5055. if(pCallSec)
  5056. {
  5057. hr = pCallSec->CloneThreadContext(TRUE);
  5058. if(FAILED(hr))
  5059. return hr;
  5060. hr = CoSwitchCallContext(pCallSec, &pOld);
  5061. if(FAILED(hr))
  5062. return hr;
  5063. }
  5064. CRevertCallSec Revert(pCallSec?TRUE:FALSE,pOld); // SEC:REVIEWED 2002-03-22 : Assumes success; why is this here? It is the only occurrence.
  5065. hr = Exec_GetObjectByPath((LPWSTR)wszClassName, 0, pContext, ppClass, NULL);
  5066. return hr;
  5067. }
  5068. //***************************************************************************
  5069. //
  5070. //***************************************************************************
  5071. STDMETHODIMP CWbemNamespace::InternalGetInstance(
  5072. LPCWSTR wszPath,
  5073. IWbemClassObject** ppInstance)
  5074. {
  5075. if (g_bDontAllowNewConnections || m_bShutDown)
  5076. {
  5077. return WBEM_E_SHUTTING_DOWN;
  5078. }
  5079. IWbemContext *pContext = NULL ;
  5080. CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ;
  5081. if (pReq == NULL)
  5082. {
  5083. pContext = ConfigMgr::GetNewContext();
  5084. if ( pContext == NULL )
  5085. return WBEM_E_OUT_OF_MEMORY;
  5086. }
  5087. else
  5088. {
  5089. pContext = pReq->GetContext();
  5090. pContext->AddRef () ; //for CReleaseMe
  5091. }
  5092. CReleaseMe _1_pContext (pContext) ;
  5093. return Exec_GetObjectByPath((LPWSTR)wszPath, 0, pContext, ppInstance, NULL);
  5094. }
  5095. //***************************************************************************
  5096. //
  5097. //***************************************************************************
  5098. STDMETHODIMP CWbemNamespace::InternalExecQuery(
  5099. LPCWSTR wszQueryLanguage,
  5100. LPCWSTR wszQuery,
  5101. long lFlags,
  5102. IWbemObjectSink* pSink)
  5103. {
  5104. if (g_bDontAllowNewConnections || m_bShutDown)
  5105. {
  5106. return WBEM_E_SHUTTING_DOWN;
  5107. }
  5108. IWbemContext *pContext = NULL ;
  5109. CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ;
  5110. if (pReq == NULL)
  5111. {
  5112. pContext = ConfigMgr::GetNewContext();
  5113. if ( pContext == NULL )
  5114. return WBEM_E_OUT_OF_MEMORY;
  5115. }
  5116. else
  5117. {
  5118. pContext = pReq->GetContext();
  5119. pContext->AddRef () ; //for CReleaseMe
  5120. }
  5121. CReleaseMe _1_pContext (pContext) ;
  5122. CSimpleWrapperSink ws(pSink);
  5123. return CQueryEngine::ExecQuery(this, (LPWSTR)wszQueryLanguage,
  5124. (LPWSTR)wszQuery, lFlags, pContext, &ws);
  5125. }
  5126. //***************************************************************************
  5127. //
  5128. //***************************************************************************
  5129. STDMETHODIMP CWbemNamespace::InternalCreateInstanceEnum(
  5130. LPCWSTR wszClassName,
  5131. long lFlags,
  5132. IWbemObjectSink* pSink)
  5133. {
  5134. if (g_bDontAllowNewConnections || m_bShutDown)
  5135. {
  5136. return WBEM_E_SHUTTING_DOWN;
  5137. }
  5138. IWbemContext *pContext = NULL ;
  5139. CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ;
  5140. if (pReq == NULL)
  5141. {
  5142. pContext = ConfigMgr::GetNewContext();
  5143. if ( pContext == NULL )
  5144. return WBEM_E_OUT_OF_MEMORY;
  5145. }
  5146. else
  5147. {
  5148. pContext = pReq->GetContext();
  5149. pContext->AddRef () ; //for CReleaseMe
  5150. }
  5151. CReleaseMe _1_pContext (pContext) ;
  5152. CSimpleWrapperSink ws(pSink);
  5153. return Exec_CreateInstanceEnum((LPWSTR)wszClassName, lFlags, pContext, &ws);
  5154. }
  5155. //***************************************************************************
  5156. //
  5157. //***************************************************************************
  5158. STDMETHODIMP CWbemNamespace::InternalPutInstance(
  5159. IWbemClassObject* pInst)
  5160. {
  5161. if (g_bDontAllowNewConnections || m_bShutDown)
  5162. {
  5163. return WBEM_E_SHUTTING_DOWN;
  5164. }
  5165. IWbemContext *pContext = NULL ;
  5166. CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ;
  5167. if (pReq == NULL)
  5168. {
  5169. pContext = ConfigMgr::GetNewContext();
  5170. if ( pContext == NULL )
  5171. return WBEM_E_OUT_OF_MEMORY;
  5172. }
  5173. else
  5174. {
  5175. pContext = pReq->GetContext();
  5176. pContext->AddRef () ; //for CReleaseMe
  5177. }
  5178. CReleaseMe _1_pContext (pContext) ;
  5179. CSynchronousSink* pSink = CSynchronousSink::Create();
  5180. if(pSink == NULL) return WBEM_E_OUT_OF_MEMORY;
  5181. pSink->AddRef();
  5182. CReleaseMe rm1(pSink);
  5183. Exec_PutInstance(pInst, 0, pContext, pSink);
  5184. HRESULT hres = WBEM_E_CRITICAL_ERROR;
  5185. pSink->GetStatus(&hres, NULL, NULL);
  5186. return hres;
  5187. }
  5188. //***************************************************************************
  5189. //
  5190. //***************************************************************************
  5191. STDMETHODIMP CWbemNamespace::GetDbInstance(
  5192. LPCWSTR wszDbKey,
  5193. IWbemClassObject** ppInstance
  5194. )
  5195. {
  5196. // ESS uses this one
  5197. return CRepository::GetObject(m_pSession, m_pScopeHandle, wszDbKey, 0, ppInstance);
  5198. }
  5199. //***************************************************************************
  5200. //
  5201. //***************************************************************************
  5202. STDMETHODIMP CWbemNamespace::GetDbReferences(
  5203. IWbemClassObject* pEndpoint,
  5204. IWbemObjectSink* pSink)
  5205. {
  5206. LPWSTR wszRelPath = ((CWbemObject*)pEndpoint)->GetRelPath();
  5207. CVectorDeleteMe<WCHAR> dm(wszRelPath);
  5208. CSimpleWrapperSink ws(pSink);
  5209. HRESULT hRes = CRepository::GetInstanceRefs(m_pSession,m_pScopeHandle, wszRelPath, &ws);
  5210. return hRes;
  5211. }
  5212. //***************************************************************************
  5213. //
  5214. //***************************************************************************
  5215. HRESULT CWbemNamespace::InternalPutStaticClass(
  5216. IWbemClassObject* pClass)
  5217. {
  5218. if (g_bDontAllowNewConnections || m_bShutDown)
  5219. {
  5220. return WBEM_E_SHUTTING_DOWN;
  5221. }
  5222. IWbemContext *pContext = NULL ;
  5223. CWbemRequest* pReq = CWbemQueue::GetCurrentRequest() ;
  5224. if (pReq == NULL)
  5225. {
  5226. pContext = ConfigMgr::GetNewContext();
  5227. if ( pContext == NULL )
  5228. return WBEM_E_OUT_OF_MEMORY;
  5229. }
  5230. else
  5231. {
  5232. pContext = pReq->GetContext();
  5233. pContext->AddRef () ; //for CReleaseMe
  5234. }
  5235. CReleaseMe _1_pContext (pContext) ;
  5236. CSynchronousSink* pSink = CSynchronousSink::Create();
  5237. if(pSink == NULL)
  5238. return WBEM_E_OUT_OF_MEMORY;
  5239. pSink->AddRef();
  5240. CReleaseMe rm1(pSink);
  5241. Exec_PutClass( pClass, 0, pContext, pSink, TRUE );
  5242. HRESULT hres = WBEM_E_CRITICAL_ERROR;
  5243. pSink->GetStatus(&hres, NULL, NULL);
  5244. return hres;
  5245. }
  5246. //***************************************************************************
  5247. //
  5248. // CWbemNamespace::AdjustPutContext
  5249. //
  5250. //***************************************************************************
  5251. HRESULT CWbemNamespace::AdjustPutContext(
  5252. IWbemContext *pCtx
  5253. )
  5254. {
  5255. // See if per-property puts are being used.
  5256. // ========================================
  5257. HRESULT hRes;
  5258. if (pCtx == 0)
  5259. return WBEM_S_NO_ERROR;
  5260. CVARIANT v;
  5261. hRes = pCtx->GetValue(L"__PUT_EXTENSIONS", 0, &v);
  5262. if (SUCCEEDED(hRes))
  5263. {
  5264. // If here, they are being used. Next we have to check and see
  5265. // if the reentrancy flag is set or not.
  5266. // =============================================================
  5267. hRes = pCtx->GetValue(L"__PUT_EXT_CLIENT_REQUEST", 0, &v);
  5268. if (SUCCEEDED(hRes))
  5269. {
  5270. pCtx->DeleteValue(L"__PUT_EXT_CLIENT_REQUEST", 0);
  5271. return WBEM_S_NO_ERROR;
  5272. }
  5273. // If here, we have to clear out the put extensions.
  5274. // =================================================
  5275. pCtx->DeleteValue(L"__PUT_EXTENSIONS", 0);
  5276. pCtx->DeleteValue(L"__PUT_EXT_CLIENT_REQUEST", 0);
  5277. pCtx->DeleteValue(L"__PUT_EXT_ATOMIC", 0);
  5278. pCtx->DeleteValue(L"__PUT_EXT_PROPERTIES", 0);
  5279. pCtx->DeleteValue(L"__PUT_EXT_STRICT_NULLS", 0);
  5280. }
  5281. return WBEM_S_NO_ERROR;
  5282. }
  5283. //***************************************************************************
  5284. //
  5285. // CWbemNamespace::MergeGetKeysCtx
  5286. //
  5287. //***************************************************************************
  5288. //
  5289. HRESULT CWbemNamespace::MergeGetKeysCtx(
  5290. IN IWbemContext *pCtx
  5291. )
  5292. {
  5293. HRESULT hRes;
  5294. if (pCtx == 0)
  5295. return WBEM_S_NO_ERROR;
  5296. CVARIANT v;
  5297. v.SetBool(TRUE);
  5298. hRes = pCtx->SetValue(L"__GET_EXTENSIONS", 0, &v);
  5299. hRes |= pCtx->SetValue(L"__GET_EXT_KEYS_ONLY", 0, &v);
  5300. hRes |= pCtx->SetValue(L"__GET_EXT_CLIENT_REQUEST", 0, &v);
  5301. return hRes;
  5302. }
  5303. //***************************************************************************
  5304. //
  5305. // CWbemNamespace::CheckNs
  5306. //
  5307. // Does a quick check on the available system resources before allowing
  5308. // a new call to proceed. Retries for 30 seconds.
  5309. //
  5310. //***************************************************************************
  5311. //
  5312. HRESULT CWbemNamespace::CheckNs()
  5313. {
  5314. HRESULT hr = WBEM_S_NO_ERROR;
  5315. if (g_bDontAllowNewConnections || m_bShutDown)
  5316. {
  5317. return WBEM_E_SHUTTING_DOWN;
  5318. }
  5319. // Quick memory check. If we are strapped for RAM/Pagefile,
  5320. // wait a while and try again. Requirements are 1 meg of
  5321. // available RAM and 1 meg of available page file.
  5322. int nRetries = 0;
  5323. for (int i = 0; i < 30; i++)
  5324. {
  5325. MEMORYSTATUS ms;
  5326. GlobalMemoryStatus(&ms);
  5327. if (ms.dwMemoryLoad < 99)
  5328. return WBEM_S_NO_ERROR;
  5329. // If here, we have to be careful. The system is loaded at 99%.
  5330. // =============================================================
  5331. if (nRetries > 30)
  5332. {
  5333. // Sixty seconds waiting for enough memory. Give up.
  5334. return WBEM_E_OUT_OF_MEMORY;
  5335. }
  5336. DWORD dwPracticalMemory = ms.dwAvailPhys + ms.dwAvailPageFile;
  5337. if (dwPracticalMemory < 0x200000) // 2 meg
  5338. {
  5339. Sleep(2000);
  5340. // Try a 1 meg allocation to see if will succeed.
  5341. LPVOID pTestMem = HeapAlloc(GetProcessHeap(), 0, 0x100000);
  5342. if (pTestMem == 0)
  5343. {
  5344. return WBEM_E_OUT_OF_MEMORY;
  5345. }
  5346. // Free the memory. The previous allocation may have
  5347. // grown the pagefile and thus we can succeed.
  5348. HeapFree(GetProcessHeap(), 0, pTestMem);
  5349. nRetries++;
  5350. }
  5351. else
  5352. {
  5353. // If here, we have a load of 99%, yet more than 2 meg of memory
  5354. // still available. Now 99% may mean there is a lot of free memory
  5355. // because the machine has huge resources or it may mean we are just
  5356. // about out of memory completely. We need hard data. If we
  5357. // have at least 5 meg anyway, this is clearly adequate, so we just
  5358. // break out of the loop and let the call continue.
  5359. //
  5360. // Otherwise, we have between 2 and 5 meg, which is starting to push
  5361. // it. We enter a waiting loop and hope for more memory. After a few
  5362. // retries if we continue to have between 2 and 5 meg, we'll let the call
  5363. // through and let the arbitrator deal with it, since the system appears
  5364. // to have stabilized at this usage.
  5365. //
  5366. hr = WBEM_S_NO_ERROR;
  5367. if (ms.dwAvailPhys < 0x200000) // If low on physical memory back off a bit for recovery via pagefile
  5368. Sleep(1000);
  5369. if (dwPracticalMemory > 0x100000 * 5) // > 5 meg; break out immediately
  5370. break;
  5371. // Under 5 meg free, retry a few times to let things clear up and get
  5372. // more memory. But, we succeed in the end anyway.
  5373. // ==================================================================
  5374. Sleep(1000);
  5375. if (nRetries++ > 5)
  5376. {
  5377. hr = WBEM_S_NO_ERROR;
  5378. break;
  5379. }
  5380. }
  5381. }
  5382. return hr;
  5383. }
  5384. //***************************************************************************
  5385. //
  5386. //***************************************************************************
  5387. //
  5388. HRESULT CWbemNamespace::UniversalConnect(
  5389. CWbemNamespace *pParent,
  5390. IWbemContext *pCtx,
  5391. LPCWSTR pszNewScope,
  5392. LPCWSTR pszAssocSelector,
  5393. LPCWSTR pszUserName,
  5394. _IWmiCallSec *pCallSec,
  5395. _IWmiUserHandle *pUser,
  5396. DWORD dwUserFlags,
  5397. DWORD dwInternalFlags,
  5398. DWORD dwSecFlags,
  5399. DWORD dwPermission,
  5400. BOOL bForClient,
  5401. BOOL bRepositOnly,
  5402. LPCWSTR pszClientMachineName,
  5403. DWORD dwClientProcessID,
  5404. IN REFIID riid,
  5405. OUT LPVOID *pConnection
  5406. )
  5407. {
  5408. HRESULT hRes;
  5409. if(dwUserFlags & WBEM_FLAG_CONNECT_REPOSITORY_ONLY)
  5410. bRepositOnly = TRUE;
  5411. // Validate.
  5412. if (pszNewScope == 0)
  5413. return WBEM_E_INVALID_PARAMETER;
  5414. if (riid != IID_IWbemServices )
  5415. return E_NOINTERFACE;
  5416. // If no parent, then this is an 'absolute' connect.
  5417. // =================================================
  5418. if (!pParent)
  5419. {
  5420. CWbemNamespace *pNs = CWbemNamespace::CreateInstance();
  5421. if (NULL == pNs) return WBEM_E_OUT_OF_MEMORY;
  5422. hRes = pNs->Initialize(
  5423. LPWSTR(pszNewScope),
  5424. LPWSTR(pszUserName),
  5425. dwSecFlags,
  5426. dwPermission,
  5427. bForClient,
  5428. bRepositOnly,
  5429. pszClientMachineName,
  5430. dwClientProcessID,
  5431. FALSE,
  5432. NULL);
  5433. if (FAILED(hRes))
  5434. {
  5435. pNs->Release();
  5436. return hRes;
  5437. }
  5438. pNs->SetIsProvider((dwUserFlags & WBEM_FLAG_CONNECT_PROVIDERS)?TRUE:FALSE);
  5439. *pConnection = pNs;
  5440. return WBEM_S_NO_ERROR;
  5441. }
  5442. else
  5443. {
  5444. return WBEM_E_INVALID_OPERATION;
  5445. }
  5446. }
  5447. //***************************************************************************
  5448. //
  5449. // Called by _IWmiCoreServices to establish a connection from the 'outside'.
  5450. //
  5451. //***************************************************************************
  5452. //
  5453. HRESULT CWbemNamespace::PathBasedConnect(
  5454. /* [in] */ LPCWSTR pszPath,
  5455. /* [in] */ LPCWSTR pszUser,
  5456. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  5457. /* [in] */ ULONG uClientFlags,
  5458. /* [in] */ DWORD dwSecFlags,
  5459. /* [in] */ DWORD dwPermissions,
  5460. /* [in] */ ULONG uInternalFlags,
  5461. /* [in] */ LPCWSTR pszClientMachineName,
  5462. /* [in] */ DWORD dwClientProcessID,
  5463. /* [in] */ REFIID riid,
  5464. /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *pServices
  5465. )
  5466. {
  5467. HRESULT hRes;
  5468. BOOL bForClient = FALSE;
  5469. if ((uInternalFlags & WMICORE_CLIENT_ORIGIN_LOCAL) ||
  5470. (uInternalFlags & WMICORE_CLIENT_ORIGIN_REMOTE) ||
  5471. (uInternalFlags & WMICORE_CLIENT_TYPE_ALT_TRANSPORT)
  5472. )
  5473. {
  5474. bForClient = TRUE;
  5475. }
  5476. hRes = UniversalConnect(
  5477. 0, // Parent CWbemNamespace; not known
  5478. pCtx, // Context
  5479. pszPath, // Path
  5480. 0, // No assoc selector at this point
  5481. pszUser, // User
  5482. 0, // Call security
  5483. 0, // User handle
  5484. uClientFlags, // Flags from client
  5485. uInternalFlags, // Internal flags
  5486. dwSecFlags, // Copy
  5487. dwPermissions, // Copy
  5488. bForClient, // For client?
  5489. FALSE, // Repository only
  5490. pszClientMachineName,
  5491. dwClientProcessID,
  5492. riid,
  5493. pServices
  5494. );
  5495. return hRes;
  5496. }
  5497. //***************************************************************************
  5498. //
  5499. //***************************************************************************
  5500. //
  5501. HRESULT CWbemNamespace::InitNewTask(
  5502. IN CAsyncReq *pReq,
  5503. IN _IWmiFinalizer *pFnz,
  5504. IN ULONG uTaskType,
  5505. IN IWbemContext *pCtx,
  5506. IN IWbemObjectSink *pAsyncClientSink
  5507. )
  5508. {
  5509. HRESULT hRes;
  5510. if (pReq == 0 || pFnz == 0)
  5511. return WBEM_E_INVALID_PARAMETER;
  5512. // Create a task for tracking the operation.
  5513. // =========================================
  5514. CWmiTask *pNewTask = CWmiTask::CreateTask();
  5515. if (pNewTask == 0)
  5516. return WBEM_E_OUT_OF_MEMORY;
  5517. CReleaseMe _2(pNewTask);
  5518. hRes = pNewTask->Initialize(this, uTaskType, pCtx, pAsyncClientSink,pReq);
  5519. if (FAILED(hRes))
  5520. return hRes;
  5521. hRes = pFnz->SetTaskHandle((_IWmiCoreHandle *) pNewTask);
  5522. if (FAILED(hRes))
  5523. return hRes;
  5524. pReq->SetTaskHandle((_IWmiCoreHandle *) pNewTask);
  5525. return WBEM_S_NO_ERROR;
  5526. }
  5527. //***************************************************************************
  5528. //
  5529. //***************************************************************************
  5530. //
  5531. HRESULT CWbemNamespace::CreateSyncFinalizer(
  5532. IN IWbemContext *pCtx,
  5533. IN _IWmiFinalizer **pResultFnz
  5534. )
  5535. {
  5536. HRESULT hRes;
  5537. ULONG uFlags = WMI_FNLZR_FLAG_FAST_TRACK;
  5538. // Determine calling context to see if the call is reentrant or what.
  5539. // ==================================================================
  5540. IWbemCausalityAccess *pCaus = 0;
  5541. if (pCtx != 0)
  5542. {
  5543. hRes = pCtx->QueryInterface(IID_IWbemCausalityAccess, (LPVOID *) &pCaus);
  5544. if (SUCCEEDED(hRes))
  5545. {
  5546. long lNumParents = 0;
  5547. long lNumSiblings = 0;
  5548. pCaus->GetHistoryInfo(&lNumParents, &lNumSiblings);
  5549. if (lNumParents)
  5550. uFlags = WMI_FNLZR_FLAG_FAST_TRACK;
  5551. pCaus->Release();
  5552. }
  5553. }
  5554. // Create Finalizer.
  5555. // =================
  5556. _IWmiFinalizer *pFnz = 0;
  5557. hRes = m_pCoreSvc->CreateFinalizer(0, &pFnz);
  5558. if (FAILED(hRes))
  5559. return hRes;
  5560. CReleaseMe _(pFnz);
  5561. hRes = pFnz->Configure(uFlags, 0);
  5562. if (FAILED(hRes))
  5563. return hRes;
  5564. pFnz->AddRef();
  5565. *pResultFnz = pFnz;
  5566. return WBEM_S_NO_ERROR;
  5567. }
  5568. //***************************************************************************
  5569. //
  5570. //***************************************************************************
  5571. //
  5572. HRESULT CWbemNamespace::CreateAsyncFinalizer(
  5573. IWbemContext *pCtx,
  5574. IWbemObjectSink *pStartingSink,
  5575. _IWmiFinalizer **pResultFnz,
  5576. IWbemObjectSink **pResultSinkEx
  5577. )
  5578. {
  5579. HRESULT hRes;
  5580. ULONG uFlags = WMI_FNLZR_FLAG_FAST_TRACK;
  5581. if ( m_bForClient )
  5582. uFlags = WMI_FNLZR_FLAG_DECOUPLED;
  5583. // Determine calling context to see if the call is reentrant or what.
  5584. // ==================================================================
  5585. IWbemCausalityAccess *pCaus = 0;
  5586. if (pCtx != 0)
  5587. {
  5588. hRes = pCtx->QueryInterface(IID_IWbemCausalityAccess, (LPVOID *) &pCaus);
  5589. if (SUCCEEDED(hRes))
  5590. {
  5591. long lNumParents = 0;
  5592. long lNumSiblings = 0;
  5593. pCaus->GetHistoryInfo(&lNumParents, &lNumSiblings);
  5594. if (lNumParents)
  5595. uFlags = WMI_FNLZR_FLAG_FAST_TRACK;
  5596. pCaus->Release();
  5597. }
  5598. }
  5599. // Create Finalizer.
  5600. // =================
  5601. _IWmiFinalizer *pFnz = 0;
  5602. hRes = m_pCoreSvc->CreateFinalizer(0, &pFnz);
  5603. if (FAILED(hRes))
  5604. return hRes;
  5605. CReleaseMe _(pFnz);
  5606. hRes = pFnz->Configure(uFlags, 0);
  5607. if (FAILED(hRes))
  5608. return hRes;
  5609. hRes = pFnz->SetDestinationSink(0, IID_IWbemObjectSink, (LPVOID) pStartingSink);
  5610. if (FAILED(hRes))
  5611. return hRes;
  5612. hRes = pFnz->NewInboundSink(0, pResultSinkEx);
  5613. if (FAILED(hRes))
  5614. return hRes;
  5615. pFnz->AddRef();
  5616. *pResultFnz = pFnz;
  5617. return WBEM_S_NO_ERROR;
  5618. }
  5619. //////////////////////////////////////////////////////////////////////////////
  5620. //////////////////////////////////////////////////////////////////////////////
  5621. //
  5622. // Native async operations
  5623. //
  5624. //////////////////////////////////////////////////////////////////////////////
  5625. //////////////////////////////////////////////////////////////////////////////
  5626. //
  5627. // InstEnum Sync[ ] Async Impl[x] AsyncEntry[x]
  5628. // ClassEnum Sync[ ] Async Impl[x] AsyncEntry[x]
  5629. //
  5630. // PutInst Sync[ ] Async Impl[x] AsyncEntry[x]
  5631. // PutClass Sync[ ] Async Impl[x] AsyncEntry[x]
  5632. // DelInst Sync[ ] Async Impl[x] AsyncEntry[x]
  5633. // DelClass Sync[ ] Async Impl[x] AsyncEntry[x]
  5634. //
  5635. // GetObject Sync[ ] Async Impl[x] AsyncEntry[x]
  5636. //
  5637. // ExecQuery Sync[ ] Async Impl[x] AsyncEntry[x]
  5638. // ExecMethod Sync[ ] Async Impl[x] AsyncEntry[x]
  5639. //
  5640. //
  5641. //***************************************************************************
  5642. //
  5643. //***************************************************************************
  5644. // ok
  5645. HRESULT CWbemNamespace::DeleteClassAsync(
  5646. const BSTR strClass,
  5647. long lFlags,
  5648. IWbemContext* pCtx,
  5649. IWbemObjectSink* pHandler
  5650. )
  5651. {
  5652. try
  5653. {
  5654. return _DeleteClassAsync(
  5655. WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_DELETE_CLASS,
  5656. 0, 0, strClass, lFlags, pCtx, pHandler
  5657. );
  5658. }
  5659. catch (...)
  5660. {
  5661. ExceptionCounter c;
  5662. return WBEM_E_CRITICAL_ERROR;
  5663. }
  5664. }
  5665. //***************************************************************************
  5666. //
  5667. //***************************************************************************
  5668. // ok
  5669. HRESULT CWbemNamespace::CreateClassEnumAsync(
  5670. const BSTR strParent,
  5671. long lFlags,
  5672. IWbemContext* pCtx,
  5673. IWbemObjectSink* pHandler
  5674. )
  5675. {
  5676. try
  5677. {
  5678. return _CreateClassEnumAsync(
  5679. WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_ENUM_CLASSES,
  5680. 0, 0, strParent, lFlags, pCtx, pHandler
  5681. );
  5682. }
  5683. catch (...)
  5684. {
  5685. ExceptionCounter c;
  5686. return WBEM_E_CRITICAL_ERROR;
  5687. }
  5688. }
  5689. //***************************************************************************
  5690. //
  5691. //***************************************************************************
  5692. // ok
  5693. HRESULT CWbemNamespace::PutClassAsync(
  5694. READONLY IWbemClassObject* pObj,
  5695. long lFlags,
  5696. IWbemContext* pCtx,
  5697. IWbemObjectSink* pHandler
  5698. )
  5699. {
  5700. try
  5701. {
  5702. return _PutClassAsync(
  5703. WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_PUT_CLASS,
  5704. 0, 0, pObj, lFlags, pCtx, pHandler
  5705. );
  5706. }
  5707. catch (...)
  5708. {
  5709. ExceptionCounter c;
  5710. return WBEM_E_CRITICAL_ERROR;
  5711. }
  5712. }
  5713. //***************************************************************************
  5714. //
  5715. //***************************************************************************
  5716. // ok
  5717. HRESULT CWbemNamespace::PutInstanceAsync(
  5718. IWbemClassObject* pInst,
  5719. long lFlags,
  5720. IWbemContext* pCtx,
  5721. IWbemObjectSink* pHandler
  5722. )
  5723. {
  5724. try
  5725. {
  5726. return _PutInstanceAsync(WMICORE_TASK_TYPE_ASYNC| WMICORE_TASK_PUT_INSTANCE,
  5727. 0, 0, pInst, lFlags, pCtx, pHandler);
  5728. }
  5729. catch (...)
  5730. {
  5731. ExceptionCounter c;
  5732. return WBEM_E_CRITICAL_ERROR;
  5733. }
  5734. }
  5735. //***************************************************************************
  5736. //
  5737. //***************************************************************************
  5738. // ok
  5739. HRESULT CWbemNamespace::DeleteInstanceAsync(
  5740. const BSTR strObjectPath,
  5741. long lFlags,
  5742. IWbemContext* pCtx,
  5743. IWbemObjectSink* pHandler
  5744. )
  5745. {
  5746. try
  5747. {
  5748. return _DeleteInstanceAsync(
  5749. WMICORE_TASK_TYPE_ASYNC| WMICORE_TASK_DELETE_INSTANCE,
  5750. 0, 0, strObjectPath, lFlags, pCtx, pHandler
  5751. );
  5752. }
  5753. catch (...)
  5754. {
  5755. ExceptionCounter c;
  5756. return WBEM_E_CRITICAL_ERROR;
  5757. }
  5758. }
  5759. //***************************************************************************
  5760. //
  5761. //***************************************************************************
  5762. // ok
  5763. HRESULT CWbemNamespace::CreateInstanceEnumAsync(
  5764. const BSTR strClass,
  5765. long lFlags,
  5766. IWbemContext* pCtx,
  5767. IWbemObjectSink* pHandler
  5768. )
  5769. {
  5770. try
  5771. {
  5772. return _CreateInstanceEnumAsync(
  5773. WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_ENUM_INSTANCES,
  5774. 0, 0,
  5775. strClass, lFlags, pCtx, pHandler
  5776. );
  5777. }
  5778. catch (...)
  5779. {
  5780. ExceptionCounter c;
  5781. return WBEM_E_CRITICAL_ERROR;
  5782. }
  5783. }
  5784. //***************************************************************************
  5785. //
  5786. //***************************************************************************
  5787. // ok
  5788. HRESULT CWbemNamespace::ExecQueryAsync(
  5789. const BSTR strQueryFormat,
  5790. const BSTR strQuery,
  5791. long lFlags,
  5792. IWbemContext* pCtx,
  5793. IWbemObjectSink* pHandler
  5794. )
  5795. {
  5796. try
  5797. {
  5798. return _ExecQueryAsync(WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_EXEC_QUERY,
  5799. 0, 0,
  5800. strQueryFormat, strQuery, lFlags, pCtx, pHandler);
  5801. }
  5802. catch(...)
  5803. {
  5804. ExceptionCounter c;
  5805. return WBEM_E_CRITICAL_ERROR;
  5806. }
  5807. }
  5808. //***************************************************************************
  5809. //
  5810. //***************************************************************************
  5811. // ok
  5812. HRESULT CWbemNamespace::ExecMethodAsync(
  5813. const BSTR ObjectPath,
  5814. const BSTR MethodName,
  5815. long lFlags,
  5816. IWbemContext *pCtx,
  5817. IWbemClassObject *pInParams,
  5818. IWbemObjectSink* pHandler
  5819. )
  5820. {
  5821. try
  5822. {
  5823. return _ExecMethodAsync(WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_EXEC_METHOD,
  5824. 0, 0,
  5825. ObjectPath,
  5826. MethodName,
  5827. lFlags,
  5828. pCtx,
  5829. pInParams,
  5830. pHandler);
  5831. }
  5832. catch (...)
  5833. {
  5834. ExceptionCounter c;
  5835. return WBEM_E_CRITICAL_ERROR;
  5836. }
  5837. }
  5838. //***************************************************************************
  5839. //
  5840. //***************************************************************************
  5841. //
  5842. HRESULT CWbemNamespace::GetObjectAsync(
  5843. const BSTR strObjectPath,
  5844. long lFlags,
  5845. IWbemContext* pCtx,
  5846. IWbemObjectSink* pHandler
  5847. )
  5848. {
  5849. HRESULT hRes = CheckNs();
  5850. if (FAILED(hRes))
  5851. return hRes;
  5852. if (!Allowed(WBEM_ENABLE))
  5853. return WBEM_E_ACCESS_DENIED;
  5854. try
  5855. {
  5856. return _GetObjectAsync(
  5857. WMICORE_TASK_TYPE_ASYNC | WMICORE_TASK_GET_OBJECT,
  5858. 0, 0,
  5859. strObjectPath,
  5860. lFlags,
  5861. pCtx,
  5862. pHandler
  5863. );
  5864. }
  5865. catch (...)
  5866. {
  5867. ExceptionCounter c;
  5868. return WBEM_E_CRITICAL_ERROR;
  5869. }
  5870. }
  5871. //
  5872. // can throw
  5873. //
  5874. ///////////////////////////////////////////////////////////////////////
  5875. HRESULT CWbemNamespace::_PutInstanceAsync(
  5876. IN ULONG uInternalFlags,
  5877. IN _IWmiFinalizer *pFnz,
  5878. IN _IWmiCoreHandle *phTask,
  5879. IWbemClassObject* pInst,
  5880. long lFlags,
  5881. IWbemContext* pCtx,
  5882. IWbemObjectSink* pHandler
  5883. )
  5884. {
  5885. HRESULT hRes = CheckNs();
  5886. if (FAILED(hRes))
  5887. return hRes;
  5888. DEBUGTRACE((LOG_WBEMCORE,
  5889. "CALL CWbemNamespace::PutInstanceAsync"
  5890. " long lFlags = 0x%X\n"
  5891. " IWbemClassObject *pInst = 0x%X\n"
  5892. " IWbemObjectSink* pHandler = 0x%X\n",
  5893. lFlags,
  5894. pInst,
  5895. pHandler
  5896. ));
  5897. // Parameter and object validation.
  5898. // ================================
  5899. if (pFnz == 0 && pHandler == 0)
  5900. return WBEM_E_INVALID_PARAMETER;
  5901. if (pInst == NULL)
  5902. return WBEM_E_INVALID_PARAMETER;
  5903. long lMainFlags = lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_OWNER_UPDATE;
  5904. if (lMainFlags != WBEM_FLAG_CREATE_ONLY &&
  5905. lMainFlags != WBEM_FLAG_UPDATE_ONLY &&
  5906. lMainFlags != WBEM_FLAG_CREATE_OR_UPDATE)
  5907. {
  5908. return WBEM_E_INVALID_PARAMETER;
  5909. }
  5910. if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE))
  5911. {
  5912. return WBEM_E_INVALID_PARAMETER;
  5913. }
  5914. if (lFlags & WBEM_FLAG_OWNER_UPDATE)
  5915. {
  5916. lFlags -= WBEM_FLAG_OWNER_UPDATE;
  5917. lFlags += WBEM_FLAG_NO_EVENTS;
  5918. }
  5919. // Check for per-property put context info.
  5920. // ========================================
  5921. if (pCtx) AdjustPutContext(pCtx);
  5922. // Create Finalizer.
  5923. // =================
  5924. IWbemObjectSink *pPseudoSink = 0;
  5925. if (pFnz == 0)
  5926. {
  5927. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  5928. if (FAILED(hRes))
  5929. return hRes;
  5930. }
  5931. else // borrowed finalizer
  5932. {
  5933. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  5934. if (FAILED(hRes))
  5935. return hRes;
  5936. pFnz->AddRef();
  5937. }
  5938. CReleaseMe _1(pPseudoSink);
  5939. CReleaseMe _2(pFnz);
  5940. // Schedule the request.
  5941. // =====================
  5942. wmilib::auto_ptr<CAsyncReq_PutInstanceAsync> pReq;
  5943. pReq.reset(new CAsyncReq_PutInstanceAsync( this, pInst, lFlags, pPseudoSink, pCtx));
  5944. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  5945. if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
  5946. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  5947. if (FAILED(hRes)) return hRes;
  5948. _1.release();
  5949. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  5950. if (FAILED(hRes))
  5951. {
  5952. pFnz->CancelTask ( 0 );
  5953. return hRes;
  5954. }
  5955. pReq.release();
  5956. return hRes;
  5957. }
  5958. //
  5959. // can throw
  5960. //
  5961. //////////////////////////////////////////////////////
  5962. HRESULT CWbemNamespace::_DeleteClassAsync(
  5963. IN ULONG uInternalFlags,
  5964. IN _IWmiFinalizer *pFnz,
  5965. IN _IWmiCoreHandle *phTask,
  5966. const BSTR strClassOrg,
  5967. long lFlags,
  5968. IWbemContext* pCtx,
  5969. IWbemObjectSink* pHandler
  5970. )
  5971. {
  5972. HRESULT hRes = CheckNs();
  5973. if (FAILED(hRes))
  5974. return hRes;
  5975. // Parameter validation.
  5976. // =====================
  5977. if (pFnz == 0 && pHandler == 0)
  5978. return WBEM_E_INVALID_PARAMETER;
  5979. if (strClassOrg == 0 || strClassOrg[0] == 0)
  5980. return WBEM_E_INVALID_PARAMETER;
  5981. if (wcslen_max(strClassOrg,g_IdentifierLimit) > g_IdentifierLimit) return WBEM_E_QUOTA_VIOLATION;
  5982. WCHAR * strClass;
  5983. if (L'\\' == strClassOrg[0] || L'/' == strClassOrg[0] )
  5984. {
  5985. strClass = wcschr(strClassOrg, L':');
  5986. if (NULL == strClass) return WBEM_E_INVALID_OBJECT_PATH;
  5987. strClass++;
  5988. if (0 == strClass[0]) return WBEM_E_INVALID_PARAMETER;
  5989. }
  5990. else
  5991. {
  5992. strClass = strClassOrg;
  5993. }
  5994. if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE))
  5995. return WBEM_E_INVALID_PARAMETER;
  5996. if (lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_OWNER_UPDATE)
  5997. return WBEM_E_INVALID_PARAMETER;
  5998. if (lFlags & WBEM_FLAG_OWNER_UPDATE)
  5999. {
  6000. lFlags -= WBEM_FLAG_OWNER_UPDATE;
  6001. lFlags += WBEM_FLAG_NO_EVENTS;
  6002. }
  6003. // Create Finalizer.
  6004. // =================
  6005. IWbemObjectSink *pPseudoSink = 0;
  6006. if (pFnz == 0)
  6007. {
  6008. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  6009. if (FAILED(hRes))
  6010. return hRes;
  6011. }
  6012. else // borrowed finalizer
  6013. {
  6014. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  6015. if (FAILED(hRes))
  6016. return hRes;
  6017. pFnz->AddRef();
  6018. }
  6019. CReleaseMe _1(pPseudoSink);
  6020. CReleaseMe _2(pFnz);
  6021. // Create request.
  6022. // ===============
  6023. wmilib::auto_ptr<CAsyncReq_DeleteClassAsync> pReq;
  6024. pReq.reset(new CAsyncReq_DeleteClassAsync( this, strClass, lFlags, pPseudoSink, pCtx));
  6025. if (pReq.get() == NULL) return WBEM_E_OUT_OF_MEMORY;
  6026. if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
  6027. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  6028. if (FAILED(hRes)) return hRes;
  6029. _1.release();
  6030. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  6031. if (FAILED(hRes))
  6032. {
  6033. pFnz->CancelTask ( 0 );
  6034. return hRes;
  6035. }
  6036. pReq.release();
  6037. return hRes;
  6038. }
  6039. //***************************************************************************
  6040. //
  6041. //***************************************************************************
  6042. //
  6043. HRESULT CWbemNamespace::_CreateClassEnumAsync(
  6044. IN ULONG uInternalFlags,
  6045. IN _IWmiFinalizer *pFnz,
  6046. IN _IWmiCoreHandle *phTask,
  6047. const BSTR strParent,
  6048. long lFlags,
  6049. IWbemContext* pCtx,
  6050. IWbemObjectSink* pHandler
  6051. )
  6052. {
  6053. HRESULT hRes = CheckNs();
  6054. if (FAILED(hRes))
  6055. return hRes;
  6056. if (!Allowed(WBEM_ENABLE))
  6057. return WBEM_E_ACCESS_DENIED;
  6058. DEBUGTRACE((LOG_WBEMCORE,
  6059. "CALL CWbemNamespace::CreateClassEnumAsync\n"
  6060. " BSTR strParent = %S\n"
  6061. " long lFlags = 0x%X\n"
  6062. " IWbemObjectSink* pHandler = 0x%X\n",
  6063. strParent,
  6064. lFlags,
  6065. pHandler
  6066. ));
  6067. // Parameter validation.
  6068. // =====================
  6069. if (pFnz == 0 && pHandler == 0)
  6070. return WBEM_E_INVALID_PARAMETER;
  6071. if (strParent)
  6072. {
  6073. if (wcslen_max(strParent,g_IdentifierLimit) > g_IdentifierLimit)
  6074. return WBEM_E_QUOTA_VIOLATION;
  6075. }
  6076. if (lFlags & ~(WBEM_FLAG_DEEP | WBEM_FLAG_SHALLOW | WBEM_FLAG_SEND_STATUS) & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS)
  6077. return WBEM_E_INVALID_PARAMETER;
  6078. // Create Finalizer.
  6079. // =================
  6080. IWbemObjectSink *pPseudoSink = 0;
  6081. if (pFnz == 0)
  6082. {
  6083. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  6084. if (FAILED(hRes))
  6085. return hRes;
  6086. }
  6087. else // borrowed finalizer
  6088. {
  6089. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  6090. if (FAILED(hRes))
  6091. return hRes;
  6092. pFnz->AddRef();
  6093. }
  6094. CReleaseMe _1(pPseudoSink);
  6095. CReleaseMe _2(pFnz);
  6096. // Add this request to the queue.
  6097. // ==============================
  6098. wmilib::auto_ptr<CAsyncReq_CreateClassEnumAsync> pReq;
  6099. pReq.reset(new CAsyncReq_CreateClassEnumAsync(this, strParent, lFlags, pPseudoSink,pCtx));
  6100. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  6101. if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
  6102. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  6103. if (FAILED(hRes)) return hRes;
  6104. _1.release();
  6105. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  6106. if (FAILED(hRes))
  6107. {
  6108. pFnz->CancelTask ( 0 );
  6109. return hRes;
  6110. }
  6111. pReq.release();
  6112. return hRes;
  6113. }
  6114. //***************************************************************************
  6115. //
  6116. //***************************************************************************
  6117. //
  6118. HRESULT CWbemNamespace::_PutClassAsync(
  6119. IN ULONG uInternalFlags,
  6120. IN _IWmiFinalizer *pFnz,
  6121. IN _IWmiCoreHandle *phTask,
  6122. READONLY IWbemClassObject* pObj,
  6123. long lFlags,
  6124. IWbemContext* pCtx,
  6125. IWbemObjectSink* pHandler
  6126. )
  6127. {
  6128. HRESULT hRes = CheckNs();
  6129. if (FAILED(hRes))
  6130. return hRes;
  6131. CVARIANT vClass;
  6132. if (pObj)
  6133. {
  6134. hRes = pObj->Get(L"__CLASS", 0, &vClass, 0, 0);
  6135. }
  6136. DEBUGTRACE((LOG_WBEMCORE,
  6137. "CALL CWbemNamespace::PutClassAsync\n"
  6138. " long lFlags = 0x%X\n"
  6139. " IWbemClassObject *pObj = 0x%X\n"
  6140. " IWbemObjectSink* pNotify = 0x%X\n"
  6141. " __CLASS=%S\n",
  6142. lFlags,
  6143. pObj,
  6144. pHandler,
  6145. vClass.GetStr()
  6146. ));
  6147. if (pFnz == 0 && pHandler == 0)
  6148. return WBEM_E_INVALID_PARAMETER;
  6149. if (pObj == NULL)
  6150. return WBEM_E_INVALID_PARAMETER;
  6151. if(!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE))
  6152. {
  6153. return WBEM_E_INVALID_PARAMETER;
  6154. }
  6155. long lTestFlags = lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_OWNER_UPDATE
  6156. & ~WBEM_MASK_UPDATE_MODE & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS;
  6157. if (!((lTestFlags == WBEM_FLAG_CREATE_OR_UPDATE) ||
  6158. (lTestFlags == WBEM_FLAG_UPDATE_ONLY) ||
  6159. (lTestFlags == WBEM_FLAG_CREATE_ONLY) ||
  6160. (lTestFlags == WBEM_FLAG_UPDATE_SAFE_MODE) ||
  6161. (lTestFlags == WBEM_FLAG_UPDATE_FORCE_MODE) ||
  6162. (lTestFlags == (WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_UPDATE_SAFE_MODE)) ||
  6163. (lTestFlags == (WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_UPDATE_FORCE_MODE))))
  6164. {
  6165. return WBEM_E_INVALID_PARAMETER;
  6166. }
  6167. if (lFlags & WBEM_FLAG_OWNER_UPDATE)
  6168. {
  6169. lFlags -= WBEM_FLAG_OWNER_UPDATE;
  6170. lFlags += WBEM_FLAG_NO_EVENTS;
  6171. }
  6172. // Create Finalizer.
  6173. // =================
  6174. IWbemObjectSink *pPseudoSink = 0;
  6175. if (pFnz == 0)
  6176. {
  6177. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  6178. if (FAILED(hRes))
  6179. return hRes;
  6180. }
  6181. else // borrowed finalizer
  6182. {
  6183. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  6184. if (FAILED(hRes))
  6185. return hRes;
  6186. pFnz->AddRef();
  6187. }
  6188. CReleaseMe _1(pPseudoSink);
  6189. CReleaseMe _2(pFnz);
  6190. // Create request.
  6191. // ===============
  6192. wmilib::auto_ptr<CAsyncReq_PutClassAsync> pReq;
  6193. pReq.reset(new CAsyncReq_PutClassAsync(this, pObj, lFlags, pPseudoSink, pCtx));
  6194. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  6195. if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
  6196. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  6197. if (FAILED(hRes)) return hRes;
  6198. _1.release();
  6199. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  6200. if (FAILED(hRes))
  6201. {
  6202. pFnz->CancelTask ( 0 );
  6203. return hRes;
  6204. }
  6205. pReq.release();
  6206. return hRes;
  6207. }
  6208. //***************************************************************************
  6209. //
  6210. //***************************************************************************
  6211. //
  6212. HRESULT CWbemNamespace::_DeleteInstanceAsync(
  6213. IN ULONG uInternalFlags,
  6214. IN _IWmiFinalizer *pFnz,
  6215. IN _IWmiCoreHandle *phTask,
  6216. READONLY const BSTR strObjectPath,
  6217. long lFlags,
  6218. IWbemContext* pCtx,
  6219. IWbemObjectSink* pHandler
  6220. )
  6221. {
  6222. HRESULT hRes = CheckNs();
  6223. if (FAILED(hRes))
  6224. return hRes;
  6225. DEBUGTRACE((LOG_WBEMCORE,
  6226. "CALL CWbemNamespace::DeleteInstance\n"
  6227. " BSTR ObjectPath = %S\n"
  6228. " long lFlags = %d\n"
  6229. " IWbemObjectSink* pHandler = 0x%X\n",
  6230. strObjectPath, lFlags, pHandler
  6231. ));
  6232. // Parameter validation.
  6233. // =====================
  6234. if (pFnz == 0 && pHandler == 0)
  6235. return WBEM_E_INVALID_PARAMETER;
  6236. if (strObjectPath == 0 || strObjectPath[0] == 0)
  6237. return WBEM_E_INVALID_PARAMETER;
  6238. if (wcslen_max(strObjectPath,g_PathLimit) > g_PathLimit)
  6239. return WBEM_E_QUOTA_VIOLATION;
  6240. if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE))
  6241. {
  6242. return WBEM_E_INVALID_PARAMETER;
  6243. }
  6244. if (lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_OWNER_UPDATE)
  6245. return WBEM_E_INVALID_PARAMETER;
  6246. if (lFlags & WBEM_FLAG_OWNER_UPDATE)
  6247. {
  6248. lFlags -= WBEM_FLAG_OWNER_UPDATE;
  6249. lFlags += WBEM_FLAG_NO_EVENTS;
  6250. }
  6251. // Create Finalizer.
  6252. // =================
  6253. IWbemObjectSink *pPseudoSink = 0;
  6254. if (pFnz == 0)
  6255. {
  6256. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  6257. if (FAILED(hRes))
  6258. return hRes;
  6259. }
  6260. else // borrowed finalizer
  6261. {
  6262. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  6263. if (FAILED(hRes))
  6264. return hRes;
  6265. pFnz->AddRef();
  6266. }
  6267. CReleaseMe _1(pPseudoSink);
  6268. CReleaseMe _2(pFnz);
  6269. // Create request.
  6270. // ===============
  6271. wmilib::auto_ptr<CAsyncReq_DeleteInstanceAsync> pReq;
  6272. pReq.reset(new CAsyncReq_DeleteInstanceAsync(this, strObjectPath, lFlags, pPseudoSink, pCtx));
  6273. if (NULL == pReq.get())return WBEM_E_OUT_OF_MEMORY;
  6274. if ( NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
  6275. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  6276. if (FAILED(hRes)) return hRes;
  6277. _1.release();
  6278. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  6279. if (FAILED(hRes))
  6280. {
  6281. pFnz->CancelTask ( 0 );
  6282. return hRes;
  6283. }
  6284. pReq.release();
  6285. return hRes;
  6286. }
  6287. //***************************************************************************
  6288. //
  6289. // CWbemNamespace::CreateInstanceEnumAsync
  6290. //
  6291. // Schedules an asynchrnous request that eventuall calls
  6292. // Exec_CreateInstanceEnum.
  6293. //
  6294. // Parameters and return values are described in help
  6295. //
  6296. //***************************************************************************
  6297. //
  6298. HRESULT CWbemNamespace::_CreateInstanceEnumAsync(
  6299. IN ULONG uInternalFlags,
  6300. IN _IWmiFinalizer *pFnz,
  6301. IN _IWmiCoreHandle *phTask,
  6302. const BSTR strClass,
  6303. long lFlags,
  6304. IWbemContext* pCtx,
  6305. IWbemObjectSink* pHandler
  6306. )
  6307. {
  6308. HRESULT hRes = CheckNs();
  6309. if (FAILED(hRes))
  6310. return hRes;
  6311. if (!Allowed(WBEM_ENABLE))
  6312. return WBEM_E_ACCESS_DENIED;
  6313. DEBUGTRACE((LOG_WBEMCORE,
  6314. "CALL CWbemNamespace::CreateInstanceEnumAsync\n"
  6315. " BSTR Class = %S\n"
  6316. " long lFlags = 0x%X\n"
  6317. " IWbemObjectSink pHandler = 0x%X\n",
  6318. strClass,
  6319. lFlags,
  6320. pHandler
  6321. ));
  6322. // Parameter validation.
  6323. // =====================
  6324. if (pFnz == 0 && pHandler == 0)
  6325. return WBEM_E_INVALID_PARAMETER;
  6326. if (strClass == 0 || strClass[0] == 0)
  6327. return WBEM_E_INVALID_PARAMETER;
  6328. if (wcslen_max(strClass,g_IdentifierLimit) > g_IdentifierLimit)
  6329. return WBEM_E_QUOTA_VIOLATION;
  6330. if (lFlags & ~(WBEM_FLAG_DEEP | WBEM_FLAG_SHALLOW | WBEM_FLAG_SEND_STATUS |
  6331. WBEM_FLAG_USE_AMENDED_QUALIFIERS | WBEM_FLAG_DIRECT_READ))
  6332. return WBEM_E_INVALID_PARAMETER;
  6333. // Create Finalizer.
  6334. // =================
  6335. IWbemObjectSink *pPseudoSink = 0;
  6336. if (pFnz == 0)
  6337. {
  6338. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  6339. if (FAILED(hRes))
  6340. return hRes;
  6341. }
  6342. else // borrowed finalizer
  6343. {
  6344. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  6345. if (FAILED(hRes))
  6346. return hRes;
  6347. pFnz->AddRef();
  6348. }
  6349. CReleaseMe _1(pPseudoSink);
  6350. CReleaseMe _2(pFnz);
  6351. // Add this request to the async queue.
  6352. // ====================================
  6353. wmilib::auto_ptr<CAsyncReq_CreateInstanceEnumAsync> pReq;
  6354. pReq.reset(new CAsyncReq_CreateInstanceEnumAsync(this, strClass, lFlags, pPseudoSink,pCtx));
  6355. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  6356. if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
  6357. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  6358. if (FAILED(hRes)) return hRes;
  6359. _1.release();
  6360. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  6361. if (FAILED(hRes))
  6362. {
  6363. pFnz->CancelTask ( 0 );
  6364. return hRes;
  6365. }
  6366. pReq.release();
  6367. return hRes;
  6368. }
  6369. //***************************************************************************
  6370. //
  6371. // CWbemNamespace::ExecQueryAsync
  6372. //
  6373. // Schedules an asynchronous request that eventually calls
  6374. // CQueryEngine::ExecQuery (see qengine.h)
  6375. //
  6376. // Parameters and return values are described in help
  6377. //
  6378. //***************************************************************************
  6379. //
  6380. HRESULT CWbemNamespace::_ExecQueryAsync(
  6381. IN ULONG uInternalFlags,
  6382. IN _IWmiFinalizer *pFnz,
  6383. IN _IWmiCoreHandle *phTask,
  6384. const BSTR strQueryFormat,
  6385. const BSTR strQuery,
  6386. long lFlags,
  6387. IWbemContext* pCtx,
  6388. IWbemObjectSink* pHandler
  6389. )
  6390. {
  6391. HRESULT hRes = CheckNs();
  6392. if (FAILED(hRes))
  6393. return hRes;
  6394. if (!Allowed(WBEM_ENABLE))
  6395. return WBEM_E_ACCESS_DENIED;
  6396. DEBUGTRACE((LOG_WBEMCORE,
  6397. "CALL CWbemNamespace::ExecQueryAsync\n"
  6398. " BSTR QueryFormat = %S\n"
  6399. " BSTR Query = %S\n"
  6400. " IWbemObjectSink* pHandler = 0x%X\n",
  6401. strQueryFormat,
  6402. strQuery,
  6403. pHandler
  6404. ));
  6405. // Parameter validation.
  6406. // =====================
  6407. if (pFnz == 0 && pHandler == 0)
  6408. return WBEM_E_INVALID_PARAMETER;
  6409. if (strQueryFormat == 0 || strQuery == 0)
  6410. return WBEM_E_INVALID_PARAMETER;
  6411. if ( 0 == strQueryFormat[0] || 0 == strQuery[0])
  6412. return WBEM_E_INVALID_PARAMETER;
  6413. if (wcslen_max(strQuery,g_QueryLimit) > g_QueryLimit) return WBEM_E_QUOTA_VIOLATION;
  6414. if (lFlags & ~WBEM_FLAG_PROTOTYPE & ~WBEM_FLAG_SEND_STATUS &
  6415. ~WBEM_FLAG_ENSURE_LOCATABLE & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS &
  6416. ~WBEM_FLAG_KEEP_SHAPE & ~WBEM_FLAG_DIRECT_READ
  6417. )
  6418. return WBEM_E_INVALID_PARAMETER;
  6419. // Create Finalizer.
  6420. // =================
  6421. IWbemObjectSink *pPseudoSink = 0;
  6422. if (pFnz == 0)
  6423. {
  6424. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  6425. if (FAILED(hRes))
  6426. return hRes;
  6427. }
  6428. else // borrowed finalizer
  6429. {
  6430. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  6431. if (FAILED(hRes))
  6432. return hRes;
  6433. pFnz->AddRef();
  6434. }
  6435. CReleaseMe rmPseudoSink(pPseudoSink);
  6436. CReleaseMe _2(pFnz);
  6437. // Add the request to the queue.
  6438. // =============================
  6439. // will throw CX_MemoryException
  6440. wmilib::auto_ptr<CAsyncReq_ExecQueryAsync> pReq;
  6441. pReq.reset(new CAsyncReq_ExecQueryAsync(this, strQueryFormat, strQuery, lFlags,pPseudoSink, pCtx));
  6442. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  6443. if ( NULL == pReq->GetContext() ) return WBEM_E_OUT_OF_MEMORY;
  6444. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  6445. if (FAILED(hRes)) return hRes;
  6446. rmPseudoSink.release();
  6447. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  6448. if (FAILED(hRes))
  6449. {
  6450. pFnz->CancelTask ( 0 );
  6451. return hRes;
  6452. }
  6453. pReq.release();
  6454. return hRes;
  6455. }
  6456. //
  6457. //
  6458. // CWbemNamespace::_GetObjectAsync
  6459. //
  6460. // Schedules an asynchrnous request that eventuall calls Exec_GetObjectByPath.
  6461. //
  6462. // Parameters and return values are described in help
  6463. //
  6464. // throws or return
  6465. //
  6466. ///////////////////////////////////////////////////////////////
  6467. HRESULT CWbemNamespace::_GetObjectAsync(
  6468. IN ULONG uInternalFlags,
  6469. IN _IWmiFinalizer *pFnz,
  6470. IN _IWmiCoreHandle *phTask,
  6471. const BSTR strObjectPath,
  6472. long lFlags,
  6473. IWbemContext* pCtx,
  6474. IWbemObjectSink* pHandler
  6475. )
  6476. {
  6477. HRESULT hRes = CheckNs();
  6478. if (FAILED(hRes))
  6479. return hRes;
  6480. DEBUGTRACE((LOG_WBEMCORE,
  6481. "CALL CWbemNamespace::GetObjectAsync\n"
  6482. " BSTR ObjectPath = %S\n"
  6483. " long lFlags = %d\n"
  6484. " IWbemObjectSink* pHandler = 0x%X\n",
  6485. strObjectPath,
  6486. lFlags,
  6487. pHandler
  6488. ));
  6489. // Parameter validation.
  6490. // =====================
  6491. if (pFnz == 0 && pHandler == 0)
  6492. return WBEM_E_INVALID_PARAMETER;
  6493. if (lFlags & ~WBEM_FLAG_SEND_STATUS & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS
  6494. & ~WBEM_FLAG_DIRECT_READ)
  6495. return WBEM_E_INVALID_PARAMETER;
  6496. // Create Finalizer.
  6497. // =================
  6498. IWbemObjectSink *pPseudoSink = 0;
  6499. if (pFnz == 0)
  6500. {
  6501. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  6502. if (FAILED(hRes))
  6503. return hRes;
  6504. }
  6505. else // borrowed finalizer
  6506. {
  6507. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  6508. if (FAILED(hRes))
  6509. return hRes;
  6510. pFnz->AddRef(); // Compensate for CReleaseMe to follow
  6511. }
  6512. CReleaseMe _1(pPseudoSink);
  6513. CReleaseMe _2(pFnz);
  6514. // Add request to the async queue.
  6515. // ===============================
  6516. wmilib::auto_ptr<CAsyncReq_GetObjectAsync> pReq;
  6517. pReq.reset(new CAsyncReq_GetObjectAsync(this, strObjectPath, lFlags, pPseudoSink, pCtx));
  6518. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  6519. if (NULL == pReq->GetContext()) return WBEM_E_OUT_OF_MEMORY;
  6520. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  6521. if (FAILED(hRes)) return hRes;
  6522. _1.release();
  6523. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  6524. if (FAILED(hRes))
  6525. {
  6526. pFnz->CancelTask(0);
  6527. return hRes;
  6528. }
  6529. pReq.release();
  6530. return hRes;
  6531. }
  6532. //
  6533. //
  6534. // CWbemNamespace::ExecMethodAsync
  6535. //
  6536. // can throw
  6537. //
  6538. //////////////////////////////////////////////////////////
  6539. HRESULT CWbemNamespace::_ExecMethodAsync(
  6540. IN ULONG uInternalFlags,
  6541. IN _IWmiFinalizer *pFnz,
  6542. IN _IWmiCoreHandle *phTask,
  6543. const BSTR ObjectPath,
  6544. const BSTR MethodName,
  6545. long lFlags,
  6546. IWbemContext *pCtx,
  6547. IWbemClassObject *pInParams,
  6548. IWbemObjectSink* pHandler
  6549. )
  6550. {
  6551. HRESULT hRes = CheckNs();
  6552. if (FAILED(hRes))
  6553. return hRes;
  6554. DEBUGTRACE((LOG_WBEMCORE,
  6555. "CALL CWbemNamespace::ExecMethodAsync\n"
  6556. " BSTR ObjectPath = %S\n"
  6557. " BSTR MethodName = %S\n"
  6558. " long lFlags = %d\n"
  6559. " IWbemClassObject * pIn = 0x%X\n",
  6560. ObjectPath, MethodName, lFlags, pInParams
  6561. ));
  6562. // Parameter validation.
  6563. // =====================
  6564. if (pFnz ==0 && pHandler == 0)
  6565. return WBEM_E_INVALID_PARAMETER;
  6566. if (lFlags & ~WBEM_FLAG_SEND_STATUS)
  6567. return WBEM_E_INVALID_PARAMETER;
  6568. // Create Finalizer.
  6569. // =================
  6570. IWbemObjectSink *pPseudoSink = 0;
  6571. if (pFnz == 0)
  6572. {
  6573. hRes = CreateAsyncFinalizer(pCtx, pHandler, &pFnz, &pPseudoSink);
  6574. if (FAILED(hRes))
  6575. return hRes;
  6576. }
  6577. else // borrowed finalizer
  6578. {
  6579. hRes = pFnz->NewInboundSink(0, &pPseudoSink);
  6580. if (FAILED(hRes))
  6581. return hRes;
  6582. pFnz->AddRef();
  6583. }
  6584. CReleaseMe _1(pPseudoSink);
  6585. CReleaseMe _2(pFnz);
  6586. // Add request to the async queue.
  6587. // ===============================
  6588. wmilib::auto_ptr<CAsyncReq_ExecMethodAsync> pReq;
  6589. pReq.reset(new CAsyncReq_ExecMethodAsync(this,
  6590. ObjectPath,
  6591. MethodName,
  6592. lFlags,
  6593. pInParams,
  6594. pPseudoSink,
  6595. pCtx));
  6596. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  6597. if ( NULL == pReq->GetContext() ) return WBEM_E_OUT_OF_MEMORY;
  6598. hRes = InitNewTask(pReq.get(), pFnz, uInternalFlags, pReq->GetContext(), pHandler);
  6599. if (FAILED(hRes)) return hRes;
  6600. _1.release();
  6601. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  6602. if (FAILED(hRes))
  6603. {
  6604. pFnz->CancelTask ( 0 );
  6605. return hRes;
  6606. }
  6607. pReq.release();
  6608. return hRes;
  6609. }
  6610. //////////////////////////////////////////////////////////////////////////////
  6611. //////////////////////////////////////////////////////////////////////////////
  6612. //
  6613. // Native sync operations
  6614. //
  6615. //////////////////////////////////////////////////////////////////////////////
  6616. //////////////////////////////////////////////////////////////////////////////
  6617. //***************************************************************************
  6618. //
  6619. // CWbemNamespace::DeleteClass
  6620. //
  6621. // Calls DeleteClassAsync and waits for completion
  6622. //
  6623. // Parameters and return values are described in help
  6624. //
  6625. //***************************************************************************
  6626. //
  6627. HRESULT CWbemNamespace::DeleteClass(
  6628. const BSTR strClass,
  6629. long lFlags,
  6630. IWbemContext* pCtx,
  6631. IWbemCallResult** ppResult
  6632. )
  6633. {
  6634. HRESULT hRes = CheckNs();
  6635. if (FAILED(hRes))
  6636. return hRes;
  6637. try
  6638. {
  6639. DEBUGTRACE((LOG_WBEMCORE,
  6640. "CALL CWbemNamespace::DeleteClass"
  6641. " BSTR Class = %S\n"
  6642. " long lFlags = 0x%X\n",
  6643. strClass,
  6644. lFlags
  6645. ));
  6646. // Parameter validation.
  6647. // =====================
  6648. if (lFlags
  6649. & ~WBEM_FLAG_RETURN_IMMEDIATELY
  6650. & ~WBEM_FLAG_OWNER_UPDATE
  6651. )
  6652. return WBEM_E_INVALID_PARAMETER;
  6653. if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL)
  6654. return WBEM_E_INVALID_PARAMETER;
  6655. // Create Finalizer.
  6656. // =================
  6657. _IWmiFinalizer *pFnz = 0;
  6658. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  6659. if (FAILED(hRes))
  6660. return hRes;
  6661. CReleaseMe _1(pFnz);
  6662. ULONG uTaskType = WMICORE_TASK_DELETE_CLASS;
  6663. if (ppResult)
  6664. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  6665. else
  6666. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  6667. // Call the async side.
  6668. // ====================
  6669. hRes = _DeleteClassAsync(uTaskType, pFnz, 0, strClass,
  6670. lFlags & ~WBEM_RETURN_IMMEDIATELY,pCtx, NULL);
  6671. if (FAILED(hRes))
  6672. return hRes;
  6673. // Check for the two return paradigms.
  6674. // ===================================
  6675. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  6676. {
  6677. HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes);
  6678. if (FAILED(hResTemp))
  6679. return hResTemp;
  6680. }
  6681. if (ppResult)
  6682. {
  6683. hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult);
  6684. }
  6685. return hRes;
  6686. }
  6687. catch(...)
  6688. {
  6689. ExceptionCounter c;
  6690. return WBEM_E_CRITICAL_ERROR;
  6691. }
  6692. }
  6693. //***************************************************************************
  6694. //
  6695. // CWbemNamespace::PutClass
  6696. //
  6697. // Calls PutClassAsync and waits for completion
  6698. //
  6699. // Parameters and return values are described in help
  6700. //
  6701. //***************************************************************************
  6702. HRESULT CWbemNamespace::PutClass(
  6703. READONLY IWbemClassObject* pObj,
  6704. long lFlags,
  6705. IWbemContext* pCtx,
  6706. NEWOBJECT IWbemCallResult** ppResult
  6707. )
  6708. {
  6709. HRESULT hRes = CheckNs();
  6710. if (FAILED(hRes))
  6711. return hRes;
  6712. CVARIANT vClass;
  6713. if (pObj)
  6714. {
  6715. hRes = pObj->Get(L"__CLASS", 0, &vClass, 0, 0);
  6716. }
  6717. DEBUGTRACE((LOG_WBEMCORE,
  6718. "CALL CWbemNamespace::PutClass\n"
  6719. " long lFlags = 0x%X\n"
  6720. " IWbemClassObject *pObj = 0x%X\n"
  6721. " __CLASS=%S\n",
  6722. lFlags,
  6723. pObj,
  6724. vClass.GetStr()
  6725. ));
  6726. if (lFlags
  6727. & ~WBEM_FLAG_RETURN_IMMEDIATELY
  6728. & ~WBEM_FLAG_OWNER_UPDATE
  6729. & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS
  6730. & ~WBEM_FLAG_CREATE_OR_UPDATE
  6731. & ~WBEM_FLAG_UPDATE_ONLY
  6732. & ~WBEM_FLAG_CREATE_ONLY
  6733. & ~WBEM_FLAG_UPDATE_SAFE_MODE
  6734. & ~WBEM_FLAG_UPDATE_FORCE_MODE
  6735. )
  6736. return WBEM_E_INVALID_PARAMETER;
  6737. if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL)
  6738. return WBEM_E_INVALID_PARAMETER;
  6739. try
  6740. {
  6741. if( ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) == 0)&&(ppResult==NULL))
  6742. {
  6743. HANDLE hCurrentToken;
  6744. if(OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE,
  6745. &hCurrentToken))
  6746. {
  6747. //
  6748. // Got a thread token --- cannot fast-track because otherwise we
  6749. // will have a thread token on a thread executing internal code
  6750. //
  6751. CloseHandle(hCurrentToken);
  6752. }
  6753. else if (CWbemQueue::GetCurrentRequest() == NULL)
  6754. {
  6755. if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE))
  6756. {
  6757. return WBEM_E_INVALID_PARAMETER;
  6758. }
  6759. if (lFlags & WBEM_FLAG_OWNER_UPDATE)
  6760. {
  6761. lFlags -= WBEM_FLAG_OWNER_UPDATE;
  6762. lFlags += WBEM_FLAG_NO_EVENTS;
  6763. }
  6764. IWbemContext *pContext = pCtx ;
  6765. if (pContext)
  6766. pContext->AddRef () ;
  6767. else
  6768. {
  6769. pContext = ConfigMgr::GetNewContext();
  6770. if ( pContext == NULL )
  6771. return WBEM_E_OUT_OF_MEMORY;
  6772. }
  6773. CReleaseMe _1_pContext (pContext) ;
  6774. CSynchronousSink *pSyncSink = CSynchronousSink::Create();
  6775. if (pSyncSink == NULL) return WBEM_E_OUT_OF_MEMORY;
  6776. pSyncSink->AddRef();
  6777. CReleaseMe _2(pSyncSink);
  6778. hRes = Exec_PutClass(pObj, lFlags, pContext, pSyncSink);
  6779. // Extract the new object from the sink.
  6780. // ======================================
  6781. pSyncSink->Block();
  6782. IWbemClassObject* pErrorObj = NULL;
  6783. pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
  6784. CReleaseMe rm1(pErrorObj);
  6785. if(pErrorObj)
  6786. {
  6787. IErrorInfo* pErrorInfo = NULL;
  6788. pErrorObj->QueryInterface(IID_IErrorInfo,(void**)&pErrorInfo);
  6789. SetErrorInfo(0, pErrorInfo);
  6790. pErrorInfo->Release();
  6791. }
  6792. return hRes;
  6793. }
  6794. }
  6795. // Create Finalizer.
  6796. // =================
  6797. _IWmiFinalizer *pFnz = 0;
  6798. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  6799. if (FAILED(hRes))
  6800. return hRes;
  6801. CReleaseMe _1(pFnz);
  6802. ULONG uTaskType = WMICORE_TASK_PUT_CLASS;
  6803. if (ppResult)
  6804. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  6805. else
  6806. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  6807. // Do the work elsewhere.
  6808. // ======================
  6809. hRes = _PutClassAsync(uTaskType, pFnz, 0, pObj, lFlags & ~WBEM_RETURN_IMMEDIATELY,
  6810. pCtx, NULL);
  6811. if (FAILED(hRes))
  6812. return hRes;
  6813. // Check for the two return paradigms.
  6814. // ===================================
  6815. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  6816. {
  6817. HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes);
  6818. if (FAILED(hResTemp))
  6819. return hResTemp;
  6820. }
  6821. if (ppResult)
  6822. {
  6823. hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult);
  6824. }
  6825. return hRes;
  6826. }
  6827. catch(...) // this interface calls the Exec_[MetrhodName] straight
  6828. {
  6829. ExceptionCounter c;
  6830. return WBEM_E_CRITICAL_ERROR;
  6831. }
  6832. }
  6833. //***************************************************************************
  6834. //
  6835. // CWbemNamespace::CancelAsyncRequest.
  6836. //
  6837. // Currently a noop, eventually this function will cancel an asynchrnous
  6838. // request based on the handle value it returned.
  6839. //
  6840. // Parameters and return values are described in help
  6841. //
  6842. //***************************************************************************
  6843. HRESULT CWbemNamespace::CancelAsyncCall(IWbemObjectSink* pSink)
  6844. {
  6845. HRESULT hRes = CheckNs();
  6846. if (FAILED(hRes))
  6847. return hRes;
  6848. // Note that LOMEM_CHECK is not needed or wanted here
  6849. if (pSink == NULL)
  6850. return WBEM_E_INVALID_PARAMETER;
  6851. // Quickly cancel via Arbitrator.
  6852. // ===============================
  6853. if (m_pArb)
  6854. {
  6855. hRes = m_pArb->CancelTasksBySink(WMIARB_CALL_CANCELLED_CLIENT, IID_IWbemObjectSink, pSink);
  6856. }
  6857. return hRes ;
  6858. }
  6859. //***************************************************************************
  6860. //
  6861. // CWbemNamespace::PutInstance
  6862. //
  6863. // Calls PutInstanceAsync and waits for completion
  6864. //
  6865. // Parameters and return values are described in help
  6866. //
  6867. //***************************************************************************
  6868. HRESULT CWbemNamespace::PutInstance(
  6869. IWbemClassObject* pInst,
  6870. long lFlags,
  6871. IWbemContext* pCtx,
  6872. IWbemCallResult** ppResult
  6873. )
  6874. {
  6875. HRESULT hRes = CheckNs();
  6876. if (FAILED(hRes))
  6877. return hRes;
  6878. // Parameter validation.
  6879. // =====================
  6880. if (lFlags
  6881. & ~WBEM_RETURN_IMMEDIATELY
  6882. & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS
  6883. & ~WBEM_FLAG_OWNER_UPDATE
  6884. & ~WBEM_FLAG_CREATE_ONLY
  6885. & ~WBEM_FLAG_UPDATE_ONLY
  6886. & ~WBEM_FLAG_CREATE_OR_UPDATE
  6887. )
  6888. return WBEM_E_INVALID_PARAMETER;
  6889. try
  6890. {
  6891. DEBUGTRACE((LOG_WBEMCORE,
  6892. "CALL CWbemNamespace::PutInstance"
  6893. " long lFlags = 0x%X\n"
  6894. " IWbemClassObject *pInst = 0x%X\n",
  6895. lFlags,
  6896. pInst));
  6897. if( ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) == 0)&&(ppResult==NULL))
  6898. {
  6899. // trick for allowing setup to set the SD
  6900. AutoRevertSecTlsFlag RevSec ( (LPVOID) 1 );
  6901. if ( IsNtSetupRunning() )
  6902. {
  6903. RevSec.SetSecTlsFlag ( (LPVOID) 0 );
  6904. }
  6905. HANDLE hCurrentToken;
  6906. if(OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE,
  6907. &hCurrentToken))
  6908. {
  6909. //
  6910. // Got a thread token --- cannot fast-track because otherwise we
  6911. // will have a thread token on a thread executing internal code
  6912. //
  6913. CloseHandle(hCurrentToken);
  6914. }
  6915. else if (CWbemQueue::GetCurrentRequest() == NULL)
  6916. {
  6917. IWbemContext *pContext = pCtx ;
  6918. if (pContext)
  6919. pContext->AddRef () ;
  6920. else
  6921. {
  6922. pContext = ConfigMgr::GetNewContext();
  6923. if ( pContext == NULL )
  6924. return WBEM_E_OUT_OF_MEMORY;
  6925. }
  6926. CReleaseMe _1_pContext (pContext) ;
  6927. CSynchronousSink *pSyncSink = CSynchronousSink::Create();
  6928. if (pSyncSink == NULL)
  6929. return WBEM_E_OUT_OF_MEMORY;
  6930. pSyncSink->AddRef();
  6931. CReleaseMe _2(pSyncSink);
  6932. if (!m_bProvider && (lFlags & WBEM_FLAG_OWNER_UPDATE))
  6933. {
  6934. return WBEM_E_INVALID_PARAMETER;
  6935. }
  6936. if (lFlags & WBEM_FLAG_OWNER_UPDATE)
  6937. {
  6938. lFlags -= WBEM_FLAG_OWNER_UPDATE;
  6939. lFlags += WBEM_FLAG_NO_EVENTS;
  6940. }
  6941. hRes = Exec_PutInstance(pInst, lFlags, pContext, pSyncSink);
  6942. // Extract the new object from the sink.
  6943. // ======================================
  6944. pSyncSink->Block();
  6945. IWbemClassObject* pErrorObj = NULL;
  6946. pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
  6947. CReleaseMe rm1(pErrorObj);
  6948. if(pErrorObj)
  6949. {
  6950. IErrorInfo* pErrorInfo = NULL;
  6951. pErrorObj->QueryInterface(IID_IErrorInfo,
  6952. (void**)&pErrorInfo);
  6953. SetErrorInfo(0, pErrorInfo);
  6954. pErrorInfo->Release();
  6955. }
  6956. return hRes;
  6957. }
  6958. }
  6959. if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL)
  6960. return WBEM_E_INVALID_PARAMETER;
  6961. // Create Finalizer.
  6962. // =================
  6963. _IWmiFinalizer *pFnz = 0;
  6964. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  6965. if (FAILED(hRes))
  6966. return hRes;
  6967. CReleaseMe _1(pFnz);
  6968. ULONG uTaskType = WMICORE_TASK_PUT_INSTANCE;
  6969. if (ppResult)
  6970. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  6971. else
  6972. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  6973. // Do the work elsewhere.
  6974. // ======================
  6975. hRes = _PutInstanceAsync(uTaskType, pFnz, 0, pInst,
  6976. lFlags & ~WBEM_RETURN_IMMEDIATELY,
  6977. pCtx, NULL);
  6978. if (FAILED(hRes))
  6979. return hRes;
  6980. // Check for the two return paradigms.
  6981. // ===================================
  6982. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  6983. {
  6984. HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes);
  6985. if (FAILED(hResTemp))
  6986. return hResTemp;
  6987. }
  6988. if (ppResult)
  6989. {
  6990. hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult);
  6991. }
  6992. return hRes;
  6993. }
  6994. catch(...) // this interfaces calls the Exec_[MethodName]
  6995. {
  6996. ExceptionCounter c;
  6997. return WBEM_E_CRITICAL_ERROR;
  6998. }
  6999. }
  7000. //***************************************************************************
  7001. //
  7002. // CWbemNamespace::DeleteInstance
  7003. //
  7004. // Calls DeleteInstanceAsync and waits for completion
  7005. //
  7006. // Parameters and return values are described in help
  7007. //
  7008. //***************************************************************************
  7009. HRESULT CWbemNamespace::DeleteInstance(
  7010. READONLY const BSTR strObjectPath,
  7011. long lFlags,
  7012. IWbemContext* pCtx,
  7013. IWbemCallResult** ppResult
  7014. )
  7015. {
  7016. HRESULT hRes = CheckNs();
  7017. if (FAILED(hRes))
  7018. return hRes;
  7019. DEBUGTRACE((LOG_WBEMCORE,
  7020. "CALL CWbemNamespace::DeleteInstance\n"
  7021. " BSTR ObjectPath = %S\n"
  7022. " long lFlags = %d\n",
  7023. strObjectPath, lFlags
  7024. ));
  7025. if (lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY &~ WBEM_FLAG_OWNER_UPDATE)
  7026. return WBEM_E_INVALID_PARAMETER;
  7027. if((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL)
  7028. return WBEM_E_INVALID_PARAMETER;
  7029. // Create Finalizer.
  7030. // =================
  7031. _IWmiFinalizer *pFnz = 0;
  7032. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  7033. if (FAILED(hRes))
  7034. return hRes;
  7035. CReleaseMe _1(pFnz);
  7036. ULONG uTaskType = WMICORE_TASK_DELETE_INSTANCE;
  7037. if (ppResult)
  7038. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  7039. else
  7040. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  7041. // Do the work elsewhere.
  7042. // ======================
  7043. hRes = _DeleteInstanceAsync(uTaskType, pFnz, 0, strObjectPath, lFlags & ~WBEM_RETURN_IMMEDIATELY,
  7044. pCtx, NULL);
  7045. if (FAILED(hRes))
  7046. return hRes;
  7047. // Check for the two return paradigms.
  7048. // ===================================
  7049. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  7050. {
  7051. HRESULT hResTemp = pFnz->GetOperationResult(0,INFINITE, &hRes);
  7052. if (FAILED(hResTemp))
  7053. return hResTemp;
  7054. }
  7055. if (ppResult)
  7056. {
  7057. hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult);
  7058. }
  7059. return hRes;
  7060. }
  7061. //***************************************************************************
  7062. //
  7063. // CWbemNamespace::GetObject
  7064. //
  7065. // Calls GetObjectAsync and waits for completion
  7066. //
  7067. // Parameters and return values are described in help
  7068. //
  7069. //***************************************************************************
  7070. HRESULT CWbemNamespace::GetObject(
  7071. READONLY const BSTR strObjectPath,
  7072. long lFlags,
  7073. IWbemContext* pCtx,
  7074. NEWOBJECT IWbemClassObject** ppObj,
  7075. NEWOBJECT IWbemCallResult** ppResult
  7076. )
  7077. {
  7078. HRESULT hRes = CheckNs();
  7079. if (FAILED(hRes))
  7080. return hRes;
  7081. if (!Allowed(WBEM_ENABLE))
  7082. return WBEM_E_ACCESS_DENIED;
  7083. DEBUGTRACE((LOG_WBEMCORE,
  7084. "CALL CWbemNamespace::GetObject\n"
  7085. " BSTR ObjectPath = %S\n"
  7086. " long lFlags = %d\n"
  7087. " IWbemClassObject ** pObj = 0x%X\n",
  7088. strObjectPath,
  7089. lFlags,
  7090. ppObj
  7091. ));
  7092. if (ppObj)
  7093. *ppObj = NULL;
  7094. if (lFlags
  7095. & ~WBEM_FLAG_RETURN_IMMEDIATELY
  7096. & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS
  7097. & ~WBEM_FLAG_DIRECT_READ
  7098. )
  7099. return WBEM_E_INVALID_PARAMETER;
  7100. if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppResult == NULL)
  7101. return WBEM_E_INVALID_PARAMETER;
  7102. try
  7103. {
  7104. if( ((lFlags & WBEM_FLAG_RETURN_IMMEDIATELY) == 0)&&(ppResult==NULL))
  7105. {
  7106. //
  7107. // This is special case GetObject synchronous. We dont want to allow this unless,
  7108. // we're running setup.
  7109. //
  7110. AutoRevertSecTlsFlag RevSec ( (LPVOID) 1 );
  7111. if ( IsNtSetupRunning() )
  7112. {
  7113. RevSec.SetSecTlsFlag ( (LPVOID) 0 );
  7114. }
  7115. HANDLE hCurrentToken;
  7116. if(OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE,
  7117. &hCurrentToken))
  7118. {
  7119. //
  7120. // Got a thread token --- cannot fast-track because otherwise we
  7121. // will have a thread token on a thread executing internal code
  7122. //
  7123. CloseHandle(hCurrentToken);
  7124. }
  7125. else if (CWbemQueue::GetCurrentRequest() == NULL)
  7126. {
  7127. IWbemContext *pContext = pCtx ;
  7128. if (pContext)
  7129. pContext->AddRef () ;
  7130. else
  7131. {
  7132. pContext = ConfigMgr::GetNewContext();
  7133. if ( pContext == NULL )
  7134. return WBEM_E_OUT_OF_MEMORY;
  7135. }
  7136. CReleaseMe _1_pContext (pContext) ;
  7137. CSynchronousSink *pSyncSink = CSynchronousSink::Create();
  7138. if (pSyncSink == NULL)
  7139. return WBEM_E_OUT_OF_MEMORY;
  7140. pSyncSink->AddRef();
  7141. CReleaseMe _2(pSyncSink);
  7142. hRes = Exec_GetObject(strObjectPath, lFlags, pContext, pSyncSink);
  7143. //if (FAILED(hRes))
  7144. //{
  7145. // return hRes;
  7146. //}
  7147. // Extract the new object from the sink.
  7148. // ======================================
  7149. pSyncSink->Block();
  7150. IWbemClassObject* pErrorObj = NULL;
  7151. pSyncSink->GetStatus(&hRes, NULL, &pErrorObj);
  7152. CReleaseMe rm1(pErrorObj);
  7153. if(pErrorObj)
  7154. {
  7155. IErrorInfo* pErrorInfo = NULL;
  7156. pErrorObj->QueryInterface(IID_IErrorInfo,
  7157. (void**)&pErrorInfo);
  7158. SetErrorInfo(0, pErrorInfo);
  7159. pErrorInfo->Release();
  7160. }
  7161. if (SUCCEEDED(hRes))
  7162. {
  7163. if(pSyncSink->GetObjects().GetSize() != 1)
  7164. return WBEM_E_CRITICAL_ERROR;
  7165. // Only access the returned object if ppObj is non-NULL.
  7166. if ( NULL != ppObj )
  7167. {
  7168. *ppObj = pSyncSink->GetObjects()[0];
  7169. (*ppObj)->AddRef();
  7170. }
  7171. }
  7172. return hRes;
  7173. }
  7174. }
  7175. // Create Finalizer.
  7176. // =================
  7177. _IWmiFinalizer *pFnz = 0;
  7178. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  7179. if (FAILED(hRes))
  7180. return hRes;
  7181. CReleaseMe _1(pFnz);
  7182. ULONG uTaskType = WMICORE_TASK_GET_OBJECT;
  7183. if (ppResult)
  7184. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  7185. else
  7186. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  7187. // Do the work elsewhere.
  7188. // ======================
  7189. hRes = _GetObjectAsync(uTaskType, pFnz, 0, strObjectPath, lFlags & ~WBEM_RETURN_IMMEDIATELY,
  7190. pCtx, NULL);
  7191. if (FAILED(hRes))
  7192. {
  7193. return hRes;
  7194. }
  7195. // Check for the two return paradigms.
  7196. // ===================================
  7197. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  7198. {
  7199. HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes);
  7200. if (FAILED(hResTemp))
  7201. return hResTemp;
  7202. if (FAILED(hRes))
  7203. return hRes;
  7204. }
  7205. if (ppResult)
  7206. {
  7207. hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult);
  7208. if (FAILED(hRes))
  7209. {
  7210. return hRes;
  7211. }
  7212. if (ppObj && ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0))
  7213. hRes = (*ppResult)->GetResultObject(INFINITE, ppObj);
  7214. }
  7215. else if (ppObj && ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0))
  7216. {
  7217. hRes = pFnz->GetResultObject(0, IID_IWbemClassObject, (LPVOID *) ppObj);
  7218. }
  7219. return hRes;
  7220. }
  7221. catch(...) // this interface goes to the Exec_[MethodName straight]
  7222. {
  7223. ExceptionCounter c;
  7224. return WBEM_E_CRITICAL_ERROR;
  7225. }
  7226. }
  7227. //***************************************************************************
  7228. //
  7229. // CWbemNamespace::ExecMethod
  7230. //
  7231. //***************************************************************************
  7232. HRESULT CWbemNamespace::ExecMethod(
  7233. const BSTR ObjectPath,
  7234. const BSTR MethodName,
  7235. long lFlags,
  7236. IWbemContext *pCtx,
  7237. IWbemClassObject *pInParams,
  7238. IWbemClassObject **ppOutParams,
  7239. IWbemCallResult **ppResult
  7240. )
  7241. {
  7242. HRESULT hRes = CheckNs();
  7243. if (FAILED(hRes))
  7244. return hRes;
  7245. DEBUGTRACE((LOG_WBEMCORE,
  7246. "CALL CWbemNamespace::ExecMethod\n"
  7247. " BSTR ObjectPath = %S\n"
  7248. " BSTR MethodName = %S\n"
  7249. " long lFlags = %d\n"
  7250. " IWbemClassObject * pIn = 0x%X\n",
  7251. ObjectPath, MethodName, lFlags, pInParams
  7252. ));
  7253. // Parameter validation.
  7254. // =====================
  7255. if (ppOutParams)
  7256. *ppOutParams = NULL;
  7257. if (lFlags & ~WBEM_FLAG_RETURN_IMMEDIATELY)
  7258. return WBEM_E_INVALID_PARAMETER;
  7259. // Create Finalizer.
  7260. // =================
  7261. _IWmiFinalizer *pFnz = 0;
  7262. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  7263. if (FAILED(hRes))
  7264. return hRes;
  7265. CReleaseMe _1(pFnz);
  7266. ULONG uTaskType = WMICORE_TASK_EXEC_METHOD;
  7267. if (ppResult)
  7268. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  7269. else
  7270. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  7271. // Do the work elsewhere.
  7272. // ======================
  7273. hRes = _ExecMethodAsync(uTaskType, pFnz, 0, ObjectPath, MethodName,
  7274. lFlags & ~WBEM_RETURN_IMMEDIATELY, pCtx, pInParams, NULL);
  7275. if (FAILED(hRes))
  7276. return hRes;
  7277. // Check for the two return paradigms.
  7278. // ===================================
  7279. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  7280. {
  7281. HRESULT hResTemp = pFnz->GetOperationResult(0, INFINITE, &hRes);
  7282. if (FAILED(hResTemp))
  7283. return hResTemp;
  7284. if (FAILED(hRes))
  7285. return hRes;
  7286. if (ppResult)
  7287. {
  7288. hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult);
  7289. if (FAILED(hRes))
  7290. return hRes;
  7291. if (ppOutParams)
  7292. {
  7293. hRes = (*ppResult)->GetResultObject(INFINITE, ppOutParams);
  7294. if (hRes == WBEM_E_NOT_FOUND) //If there was no object we still return success!
  7295. hRes = WBEM_S_NO_ERROR;
  7296. }
  7297. }
  7298. else
  7299. {
  7300. hRes = pFnz->GetResultObject(0, IID_IWbemClassObject, (LPVOID *) ppOutParams);
  7301. if (hRes == WBEM_E_NOT_FOUND) //If there was no object we still return success!
  7302. hRes = WBEM_S_NO_ERROR;
  7303. }
  7304. }
  7305. else
  7306. {
  7307. //
  7308. // If we have a call result pointer we should try to use it
  7309. //
  7310. if ( ppResult )
  7311. {
  7312. hRes = pFnz->GetResultObject(0, IID_IWbemCallResult, (LPVOID *) ppResult);
  7313. if (hRes == WBEM_E_NOT_FOUND) //If there was no object we still return success!
  7314. hRes = WBEM_S_NO_ERROR;
  7315. }
  7316. else // semysync and nobody interested
  7317. {
  7318. pFnz->CancelTask(0);
  7319. hRes = WBEM_S_NO_ERROR;
  7320. }
  7321. }
  7322. return hRes;
  7323. }
  7324. //***************************************************************************
  7325. //
  7326. // CWbemNamespace::CreateInstanceEnum
  7327. //
  7328. // Calls CreateInstanceEnumAsync and waits for completion
  7329. //
  7330. // Parameters and return values are described in help
  7331. //
  7332. //***************************************************************************
  7333. HRESULT CWbemNamespace::CreateInstanceEnum(
  7334. const BSTR strClass,
  7335. long lFlags,
  7336. IWbemContext* pCtx,
  7337. IEnumWbemClassObject** ppEnum
  7338. )
  7339. {
  7340. HRESULT hRes = CheckNs();
  7341. if (FAILED(hRes))
  7342. return hRes;
  7343. DEBUGTRACE((LOG_WBEMCORE,
  7344. "CALL CWbemNamespace::CreateInstanceEnum\n"
  7345. " long lFlags = 0x%X\n"
  7346. " BSTR Class = %S\n"
  7347. " IEnumWbemClassObject **pEnum = 0x%X\n",
  7348. lFlags,
  7349. strClass,
  7350. ppEnum
  7351. ));
  7352. // Validate parameters
  7353. // ===================
  7354. if (lFlags
  7355. & ~WBEM_RETURN_IMMEDIATELY
  7356. & ~WBEM_FLAG_FORWARD_ONLY
  7357. & ~WBEM_FLAG_DEEP
  7358. & ~WBEM_FLAG_SHALLOW
  7359. & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS
  7360. & ~WBEM_FLAG_DIRECT_READ
  7361. )
  7362. return WBEM_E_INVALID_PARAMETER;
  7363. if (ppEnum == NULL)
  7364. return WBEM_E_INVALID_PARAMETER;
  7365. *ppEnum = NULL;
  7366. // Create Finalizer.
  7367. // =================
  7368. _IWmiFinalizer *pFnz = 0;
  7369. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  7370. if (FAILED(hRes))
  7371. return hRes;
  7372. CReleaseMe _1(pFnz);
  7373. ULONG uTaskType = WMICORE_TASK_ENUM_INSTANCES;
  7374. if (lFlags & WBEM_RETURN_IMMEDIATELY)
  7375. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  7376. else
  7377. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  7378. // Do the work.
  7379. // ============
  7380. hRes = _CreateInstanceEnumAsync(uTaskType, pFnz, 0, strClass,
  7381. lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY,
  7382. pCtx, NULL);
  7383. if (FAILED(hRes))
  7384. return hRes;
  7385. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  7386. pFnz->GetOperationResult(0, INFINITE, &hRes);
  7387. if (SUCCEEDED(hRes))
  7388. {
  7389. IEnumWbemClassObject* pEnum = NULL;
  7390. HRESULT hResTemp = pFnz->GetResultObject(lFlags, IID_IEnumWbemClassObject, (LPVOID*)&pEnum);
  7391. if (FAILED(hResTemp))
  7392. return hResTemp;
  7393. CReleaseMe _2(pEnum);
  7394. *ppEnum = pEnum;
  7395. pEnum->AddRef(); // counteract CReleaseMe
  7396. }
  7397. return hRes;
  7398. }
  7399. //***************************************************************************
  7400. //
  7401. // CWbemNamespace::CreateClassEnum
  7402. //
  7403. // Invokes CreateClassEnumAsync and waits for completion. Actual work is
  7404. // performed in Exec_CreateClassEnum.
  7405. //
  7406. // Parameters and return values are described in help
  7407. //
  7408. //***************************************************************************
  7409. HRESULT CWbemNamespace::CreateClassEnum(
  7410. const BSTR strParent,
  7411. long lFlags,
  7412. IWbemContext* pCtx,
  7413. IEnumWbemClassObject **ppEnum
  7414. )
  7415. {
  7416. HRESULT hRes = CheckNs();
  7417. if (FAILED(hRes))
  7418. return hRes;
  7419. DEBUGTRACE((LOG_WBEMCORE,
  7420. "CALL CWbemNamespace::CreateClassEnum\n"
  7421. " BSTR Parent = %S\n"
  7422. " long lFlags = 0x%X\n"
  7423. " IEnumWbemClassObject = 0x%X\n",
  7424. strParent,
  7425. lFlags,
  7426. ppEnum
  7427. ));
  7428. // Validate parameters
  7429. // ===================
  7430. if (lFlags
  7431. & ~WBEM_FLAG_DEEP
  7432. & ~WBEM_FLAG_SHALLOW
  7433. & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS
  7434. & ~WBEM_FLAG_RETURN_IMMEDIATELY
  7435. & ~WBEM_FLAG_FORWARD_ONLY
  7436. )
  7437. return WBEM_E_INVALID_PARAMETER;
  7438. if (ppEnum == NULL)
  7439. return WBEM_E_INVALID_PARAMETER;
  7440. *ppEnum = NULL;
  7441. // Create Finalizer.
  7442. // =================
  7443. _IWmiFinalizer *pFnz = 0;
  7444. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  7445. if (FAILED(hRes))
  7446. return hRes;
  7447. CReleaseMe _1(pFnz);
  7448. ULONG uTaskType = WMICORE_TASK_ENUM_CLASSES;
  7449. if (lFlags & WBEM_RETURN_IMMEDIATELY)
  7450. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  7451. else
  7452. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  7453. // Do the work.
  7454. // ============
  7455. hRes = _CreateClassEnumAsync(uTaskType, pFnz, 0, strParent,
  7456. lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY,
  7457. pCtx, NULL);
  7458. if (FAILED(hRes))
  7459. return hRes;
  7460. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  7461. pFnz->GetOperationResult(0, INFINITE, &hRes);
  7462. if (SUCCEEDED(hRes))
  7463. {
  7464. IEnumWbemClassObject* pEnum = NULL;
  7465. HRESULT hResTemp = pFnz->GetResultObject(lFlags, IID_IEnumWbemClassObject, (LPVOID*)&pEnum);
  7466. if (FAILED(hResTemp))
  7467. return hResTemp;
  7468. CReleaseMe _2(pEnum);
  7469. *ppEnum = pEnum;
  7470. pEnum->AddRef(); // Counteract CReleaseMe
  7471. }
  7472. return hRes;
  7473. }
  7474. //***************************************************************************
  7475. //
  7476. //***************************************************************************
  7477. HRESULT CWbemNamespace::ExecQuery(
  7478. READONLY const BSTR strQueryFormat,
  7479. READONLY const BSTR strQuery,
  7480. long lFlags,
  7481. IWbemContext* pCtx,
  7482. NEWOBJECT IEnumWbemClassObject** ppEnum
  7483. )
  7484. {
  7485. HRESULT hRes = CheckNs();
  7486. if (FAILED(hRes))
  7487. return hRes;
  7488. DEBUGTRACE((LOG_WBEMCORE,
  7489. "CALL CWbemNamespace::ExecQuery\n"
  7490. " BSTR QueryFormat = %S\n"
  7491. " BSTR Query = %S\n"
  7492. " IEnumWbemClassObject **pEnum = 0x%X\n",
  7493. strQueryFormat,
  7494. strQuery,
  7495. ppEnum
  7496. ));
  7497. // Validate parameters
  7498. // ===================
  7499. if (lFlags
  7500. & ~WBEM_FLAG_PROTOTYPE
  7501. & ~WBEM_FLAG_ENSURE_LOCATABLE
  7502. & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS
  7503. & ~WBEM_FLAG_KEEP_SHAPE
  7504. & ~WBEM_RETURN_IMMEDIATELY
  7505. & ~WBEM_FLAG_FORWARD_ONLY
  7506. & ~WBEM_FLAG_DIRECT_READ
  7507. )
  7508. return WBEM_E_INVALID_PARAMETER;
  7509. if (ppEnum == NULL)
  7510. return WBEM_E_INVALID_PARAMETER;
  7511. try
  7512. {
  7513. *ppEnum = NULL;
  7514. // Create Finalizer.
  7515. _IWmiFinalizer *pFnz = 0;
  7516. hRes = CreateSyncFinalizer(pCtx, &pFnz);
  7517. if (FAILED(hRes))
  7518. return hRes;
  7519. CReleaseMe _1(pFnz);
  7520. ULONG uTaskType = WMICORE_TASK_EXEC_QUERY;
  7521. if (lFlags & WBEM_RETURN_IMMEDIATELY)
  7522. uTaskType |= WMICORE_TASK_TYPE_SEMISYNC;
  7523. else
  7524. uTaskType |= WMICORE_TASK_TYPE_SYNC;
  7525. // Do the work.
  7526. // ============
  7527. hRes = _ExecQueryAsync(uTaskType, pFnz, 0, strQueryFormat, strQuery,
  7528. lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_FORWARD_ONLY,
  7529. pCtx, NULL);
  7530. if (FAILED(hRes))
  7531. return hRes;
  7532. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  7533. pFnz->GetOperationResult(0, INFINITE, &hRes);
  7534. if (SUCCEEDED(hRes))
  7535. {
  7536. IEnumWbemClassObject* pEnum = NULL;
  7537. HRESULT hResTemp = pFnz->GetResultObject(lFlags, IID_IEnumWbemClassObject, (LPVOID*)&pEnum);
  7538. if (FAILED(hResTemp))
  7539. return hResTemp;
  7540. CReleaseMe _2(pEnum);
  7541. *ppEnum = pEnum;
  7542. pEnum->AddRef(); // Counteract CReleaseMe
  7543. }
  7544. return hRes;
  7545. }
  7546. catch(CX_MemoryException &)
  7547. {
  7548. return WBEM_E_OUT_OF_MEMORY;
  7549. }
  7550. catch(...)
  7551. {
  7552. ExceptionCounter c;
  7553. return WBEM_E_CRITICAL_ERROR;
  7554. }
  7555. }
  7556. //***************************************************************************
  7557. //
  7558. // CWbemNamespace::QueryObjectSink
  7559. //
  7560. // Returns the pointer to the ESS event handler. Clients can use this pointer
  7561. // to supply events to WINMGMT. NOTE: this pointer will be NULL if ESS is
  7562. // disabled (see cfgmgr.h).
  7563. //
  7564. // Parameters and return values are described in help
  7565. //
  7566. //***************************************************************************
  7567. HRESULT CWbemNamespace::QueryObjectSink(
  7568. long lFlags,
  7569. IWbemObjectSink** ppHandler
  7570. )
  7571. {
  7572. HRESULT hRes = CheckNs();
  7573. if (FAILED(hRes))
  7574. return hRes;
  7575. if (!Allowed(WBEM_FULL_WRITE_REP))
  7576. return WBEM_E_ACCESS_DENIED;
  7577. if (ppHandler == NULL)
  7578. return WBEM_E_INVALID_PARAMETER;
  7579. *ppHandler = NULL;
  7580. if (lFlags != 0)
  7581. return WBEM_E_INVALID_PARAMETER;
  7582. IWbemEventSubsystem_m4* pEss = ConfigMgr::GetEssSink();
  7583. if (pEss)
  7584. {
  7585. CReleaseMe rm_(pEss);
  7586. CWbemPtr<IWbemObjectSink> pEssSink;
  7587. hRes = pEss->GetNamespaceSink(m_pThisNamespaceFull, &pEssSink);
  7588. if ( FAILED(hRes)) return hRes;
  7589. CWbemPtr<CSecureEssNamespaceSink> pSecureSink = new CSecureEssNamespaceSink(this,pEssSink);
  7590. if ( pSecureSink == NULL )
  7591. return WBEM_E_OUT_OF_MEMORY;
  7592. hRes = pSecureSink->QueryInterface( IID_IWbemObjectSink,
  7593. (void**)ppHandler );
  7594. return hRes;
  7595. }
  7596. else
  7597. {
  7598. return WBEM_E_NOT_SUPPORTED;
  7599. }
  7600. }
  7601. //***************************************************************************
  7602. //
  7603. // CWbemNamespace::OpenNamespace
  7604. //
  7605. // Opens a child namespace of this one. Username, password, locale id,
  7606. // flags and error object parameters are ignored.
  7607. //
  7608. // Parameters:
  7609. //
  7610. // BSTR NsPath Relative path to the namespace
  7611. // BSTR User Reserved, must be NULL.
  7612. // BSTR Password Reserved, must be NULL.
  7613. // long lLocaleId Reserved, must be NULL.
  7614. // long lFlags Reserved, must be NULL.
  7615. // IWbemServices **pNewContext Destination for the new namespace pointer.
  7616. // Must be released by the caller.
  7617. // IWbemClassObject** ppErrorObj Reserved, must be NULL.
  7618. //
  7619. // RETURN VALUES:
  7620. //
  7621. // WBEM_S_NO_ERROR On success
  7622. // WBEM_E_INVALID_PARAMETER Invalid name.
  7623. //
  7624. //***************************************************************************
  7625. HRESULT CWbemNamespace::OpenNamespace(
  7626. const BSTR NsPath,
  7627. long lFlags,
  7628. IWbemContext* pCtx,
  7629. IWbemServices **ppNewNamespace,
  7630. IWbemCallResult **ppResult
  7631. )
  7632. {
  7633. HRESULT hRes = CheckNs();
  7634. if (FAILED(hRes))
  7635. return hRes;
  7636. DEBUGTRACE((LOG_WBEMCORE,
  7637. "CALL CWbemNamespace::OpenNamespace\n"
  7638. " BSTR NsPath = %S\n"
  7639. " long lFlags = %d\n"
  7640. " IWbemContext* pCtx = 0x%X\n"
  7641. " IWbemServices **pNewContext = 0x%X\n",
  7642. NsPath,
  7643. lFlags,
  7644. pCtx,
  7645. ppNewNamespace
  7646. ));
  7647. // Parameter validation.
  7648. // =====================
  7649. try
  7650. {
  7651. if (NsPath == 0 || wcslen(NsPath) == 0 || // SEC:REVIEWED 2002-03-22 : OK
  7652. (ppNewNamespace == NULL && ppResult == NULL))
  7653. {
  7654. return WBEM_E_INVALID_PARAMETER;
  7655. }
  7656. if (ppNewNamespace == NULL && (lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  7657. {
  7658. return WBEM_E_INVALID_PARAMETER;
  7659. }
  7660. if ((lFlags & WBEM_RETURN_IMMEDIATELY) && ppNewNamespace)
  7661. return WBEM_E_INVALID_PARAMETER;
  7662. if(ppNewNamespace)
  7663. *ppNewNamespace = NULL;
  7664. if(ppResult)
  7665. *ppResult = NULL;
  7666. if((lFlags & ~WBEM_RETURN_IMMEDIATELY & ~WBEM_FLAG_USE_AMENDED_QUALIFIERS & ~WBEM_FLAG_CONNECT_REPOSITORY_ONLY) != 0)
  7667. return WBEM_E_INVALID_PARAMETER;
  7668. bool bWin9XLocalSecurity = false;
  7669. // If here, we found the object, so we open the
  7670. // corresponding namespace.
  7671. // ============================================
  7672. WString NewNs = m_pThisNamespace;
  7673. NewNs += L"\\";
  7674. NewNs += NsPath;
  7675. CCallResult* pResult = new CCallResult;
  7676. if(pResult == NULL) return WBEM_E_OUT_OF_MEMORY;
  7677. CReleaseMe rmResult(pResult);
  7678. // Schedule a request and wait
  7679. // ===========================
  7680. bool bForClient = m_bForClient ? true : false;
  7681. wmilib::auto_ptr<CAsyncReq_OpenNamespace> pReq;
  7682. pReq.reset( new CAsyncReq_OpenNamespace(this,
  7683. NewNs,
  7684. (bWin9XLocalSecurity) ? SecFlagWin9XLocal : lFlags & WBEM_FLAG_CONNECT_REPOSITORY_ONLY,
  7685. (bWin9XLocalSecurity) ? m_dwPermission : 0,
  7686. pCtx, pResult, bForClient));
  7687. if (NULL == pReq.get()) return WBEM_E_OUT_OF_MEMORY;
  7688. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  7689. if (FAILED(hRes)) return hRes;
  7690. pReq.release(); // ownership transferred to queue
  7691. if (ppResult)
  7692. {
  7693. *ppResult = pResult;
  7694. pResult->AddRef();
  7695. }
  7696. if ((lFlags & WBEM_RETURN_IMMEDIATELY) == 0)
  7697. {
  7698. hRes = pResult->GetResultServices(INFINITE, ppNewNamespace);
  7699. }
  7700. return hRes;
  7701. }
  7702. catch(...)
  7703. {
  7704. ExceptionCounter c;
  7705. return WBEM_E_FAILED;
  7706. }
  7707. }
  7708. //***************************************************************************
  7709. //
  7710. //***************************************************************************
  7711. //
  7712. HRESULT CWbemNamespace::DeleteObject(
  7713. IN const BSTR strObjectPath,
  7714. IN long lFlags,
  7715. IN IWbemContext __RPC_FAR *pCtx,
  7716. /* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult
  7717. )
  7718. {
  7719. HRESULT hRes;
  7720. ULONGLONG uInf;
  7721. // Parse the path and determine if a class or instance.
  7722. IWbemPath *pPath = ConfigMgr::GetNewPath();
  7723. CReleaseMe _(pPath);
  7724. hRes = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, strObjectPath);
  7725. if (FAILED(hRes))
  7726. return hRes;
  7727. hRes = pPath->GetInfo(0, &uInf);
  7728. if (FAILED(hRes))
  7729. return hRes;
  7730. if (uInf & WBEMPATH_INFO_IS_CLASS_REF)
  7731. return DeleteClass(strObjectPath, lFlags, pCtx, ppCallResult);
  7732. else if (uInf & WBEMPATH_INFO_IS_INST_REF)
  7733. return DeleteInstance(strObjectPath, lFlags, pCtx, ppCallResult);
  7734. else
  7735. return WBEM_E_INVALID_PARAMETER;
  7736. }
  7737. //***************************************************************************
  7738. //
  7739. //***************************************************************************
  7740. //
  7741. HRESULT CWbemNamespace::ExecSyncQuery(
  7742. IN LPWSTR pszQuery,
  7743. IN IWbemContext *pCtx,
  7744. IN LONG lFlags,
  7745. OUT CFlexArray &aDest
  7746. )
  7747. {
  7748. HRESULT hRes;
  7749. CSynchronousSink* pSink = CSynchronousSink::Create();
  7750. if (NULL == pSink) return WBEM_E_OUT_OF_MEMORY;
  7751. pSink->AddRef();
  7752. CReleaseMe _1(pSink);
  7753. hRes = CQueryEngine::ExecQuery(this, L"WQL", pszQuery, lFlags, pCtx, pSink);
  7754. if (FAILED(hRes)) return hRes;
  7755. pSink->Block();
  7756. pSink->GetStatus(&hRes, NULL, NULL);
  7757. if (FAILED(hRes)) return hRes;
  7758. aDest.Bind(pSink->GetObjects().GetArray());
  7759. return WBEM_S_NO_ERROR;
  7760. }
  7761. //***************************************************************************
  7762. //
  7763. // CWbemNamespace::MapAssocRefsToClasses
  7764. //
  7765. // Analyzes the association and determines which reference properties
  7766. // point to which endpoints. <pszAssocRef1> is the ref property
  7767. // which can point to instances of <pClsDef1> and <pszAssocRef2> is
  7768. // the property which can point to instances of <pClsDef2>.
  7769. //
  7770. //***************************************************************************
  7771. //
  7772. HRESULT CWbemNamespace::MapAssocRefsToClasses(
  7773. IN IWbemClassObject *pAssocClass,
  7774. IN IWbemClassObject *pClsDef1,
  7775. IN IWbemClassObject *pClsDef2,
  7776. wmilib::auto_buffer<WCHAR> & pszAssocRef1,
  7777. wmilib::auto_buffer<WCHAR> & pszAssocRef2)
  7778. {
  7779. HRESULT hRes;
  7780. // Note 97: Not valid for ternary assoc types
  7781. // or derived types.
  7782. // ===========================================
  7783. // For each ref property, see if it can point to one of the endpoints.
  7784. // ===================================================================
  7785. pAssocClass->BeginEnumeration(WBEM_FLAG_REFS_ONLY);
  7786. while (1)
  7787. {
  7788. BSTR strPropName = 0;
  7789. hRes = pAssocClass->Next(0,&strPropName,0,0,0);
  7790. CSysFreeMe _1(strPropName);
  7791. if (hRes == WBEM_S_NO_MORE_DATA) break;
  7792. hRes = CAssocQuery::RoleTest(pClsDef1, pAssocClass, this, strPropName, ROLETEST_MODE_CIMREF_TYPE);
  7793. if (SUCCEEDED(hRes))
  7794. {
  7795. pszAssocRef1.reset(Macro_CloneLPWSTR(strPropName));
  7796. if (NULL == pszAssocRef1.get()) return WBEM_E_OUT_OF_MEMORY;
  7797. continue;
  7798. }
  7799. hRes = CAssocQuery::RoleTest(pClsDef2, pAssocClass, this, strPropName, ROLETEST_MODE_CIMREF_TYPE);
  7800. if (SUCCEEDED(hRes))
  7801. {
  7802. pszAssocRef2.reset(Macro_CloneLPWSTR(strPropName));
  7803. if (NULL == pszAssocRef2.get()) return WBEM_E_OUT_OF_MEMORY;
  7804. continue;
  7805. }
  7806. } // Enum of ref properties
  7807. pAssocClass->EndEnumeration();
  7808. if (NULL == pszAssocRef1.get() ||NULL == pszAssocRef2.get())
  7809. {
  7810. pszAssocRef1.reset(NULL);
  7811. pszAssocRef2.reset(NULL);
  7812. return WBEM_E_FAILED;
  7813. }
  7814. return WBEM_S_NO_ERROR;
  7815. }
  7816. //***************************************************************************
  7817. //
  7818. //***************************************************************************
  7819. //
  7820. HRESULT CWbemNamespace::BuildAssocTriads(
  7821. IN IWbemClassObject *pAssocClass, // Assoc class
  7822. IN IWbemClassObject *pClsDef1, // Class for EP1
  7823. IN IWbemClassObject *pClsDef2, // Class for EP2
  7824. IN LPWSTR pszJoinProp1, // Matching prop in EP1
  7825. IN LPWSTR pszJoinProp2, // Matching prop in EP2
  7826. IN LPWSTR pszAssocRef1, // Prop which points to EP1
  7827. IN LPWSTR pszAssocRef2, // Prop which points to EP2
  7828. IN CFlexArray &aEp1, // EP1 instances
  7829. IN CFlexArray &aEp2, // EP2 instances
  7830. IN OUT CFlexArray &aTriads // OUT : Triad list
  7831. )
  7832. {
  7833. HRESULT hRes = WBEM_S_NO_ERROR;
  7834. if (pszJoinProp1 == 0 || pszJoinProp2 == 0 || pAssocClass == 0 ||
  7835. pszAssocRef1 == 0 || pszAssocRef2 == 0)
  7836. return WBEM_E_INVALID_PARAMETER;
  7837. // Do the matching.
  7838. // ================
  7839. for (int i = 0; i < aEp1.Size(); i++)
  7840. {
  7841. IWbemClassObject *pObj1 = (IWbemClassObject *) aEp1[i];
  7842. CVARIANT v1;
  7843. if (FAILED(hRes = pObj1->Get(pszJoinProp1, 0, &v1, 0, 0))) return hRes;
  7844. for (int i2 = 0; i2 < aEp2.Size(); i2++)
  7845. {
  7846. BOOL bMatch = FALSE;
  7847. IWbemClassObject *pObj2 = (IWbemClassObject *) aEp2[i2];
  7848. CVARIANT v2;
  7849. pObj2->Get(pszJoinProp2, 0, &v2, 0, 0);
  7850. if (V_VT(&v1) == VT_I4 && V_VT(&v2) == VT_I4)
  7851. {
  7852. if (v1.GetLONG() == v2.GetLONG())
  7853. {
  7854. bMatch = TRUE;
  7855. }
  7856. }
  7857. else if (V_VT(&v1) == VT_BSTR && V_VT(&v2) == VT_BSTR)
  7858. {
  7859. if (wbem_wcsicmp(v1.GetStr(), v2.GetStr()) == 0)
  7860. {
  7861. bMatch = TRUE;
  7862. }
  7863. }
  7864. // If a match, spawn the association and bind it.
  7865. // ==============================================
  7866. if (bMatch)
  7867. {
  7868. IWbemClassObject *pAssocInst = 0;
  7869. if (FAILED(hRes = pAssocClass->SpawnInstance(0, &pAssocInst))) return hRes;
  7870. CReleaseMe rmAssoc(pAssocInst);
  7871. CVARIANT vPath1, vPath2;
  7872. if (FAILED(hRes = pObj1->Get(L"__RELPATH", 0, &vPath1, 0, 0))) return hRes;
  7873. if (FAILED(hRes = pObj2->Get(L"__RELPATH", 0, &vPath2, 0, 0))) return hRes;
  7874. if (FAILED(hRes = pAssocInst->Put(pszAssocRef1, 0, &vPath1, 0))) return hRes;
  7875. if (FAILED(hRes = pAssocInst->Put(pszAssocRef2, 0, &vPath2, 0))) return hRes;
  7876. wmilib::auto_ptr<SAssocTriad> pTriad( new SAssocTriad);
  7877. if (NULL == pTriad.get()) return WBEM_E_OUT_OF_MEMORY;
  7878. pTriad->m_pEp1 = pObj1;
  7879. pTriad->m_pEp1->AddRef();
  7880. pTriad->m_pEp2 = pObj2;
  7881. pTriad->m_pEp2->AddRef();
  7882. pTriad->m_pAssoc = pAssocInst;
  7883. pTriad->m_pAssoc->AddRef();
  7884. if (CFlexArray::no_error != aTriads.Add(pTriad.get())) return WBEM_E_OUT_OF_MEMORY;
  7885. pTriad.release();
  7886. }
  7887. }
  7888. }
  7889. return hRes;
  7890. }
  7891. //***************************************************************************
  7892. //
  7893. //***************************************************************************
  7894. //
  7895. HRESULT CWbemNamespace::ExtractEpInfoFromQuery(
  7896. IN IWbemQuery *pQuery,
  7897. wmilib::auto_buffer<WCHAR> & pszRetClass1,
  7898. wmilib::auto_buffer<WCHAR> & pszRetProp1,
  7899. wmilib::auto_buffer<WCHAR> & pszRetClass2,
  7900. wmilib::auto_buffer<WCHAR> & pszRetProp2
  7901. )
  7902. {
  7903. HRESULT hRes;
  7904. SWQLNode *pRoot;
  7905. hRes = pQuery->GetAnalysis(
  7906. WMIQ_ANALYSIS_RESERVED,
  7907. 0,
  7908. (LPVOID *) &pRoot
  7909. );
  7910. if (FAILED(hRes))
  7911. return hRes;
  7912. // Move down the parse tree to find the JOIN clause.
  7913. // =================================================
  7914. if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_QueryRoot)
  7915. return WBEM_E_INVALID_QUERY;
  7916. pRoot = pRoot->m_pLeft;
  7917. if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_Select)
  7918. return WBEM_E_INVALID_QUERY;
  7919. pRoot = pRoot->m_pLeft;
  7920. if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_TableRefs)
  7921. return WBEM_E_INVALID_QUERY;
  7922. pRoot = pRoot->m_pRight;
  7923. if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_FromClause)
  7924. return WBEM_E_INVALID_QUERY;
  7925. pRoot = pRoot->m_pLeft;
  7926. if (!pRoot || pRoot->m_dwNodeType != TYPE_SWQLNode_Join)
  7927. return WBEM_E_INVALID_QUERY;
  7928. // We are now at the JOIN node.
  7929. // ============================
  7930. SWQLNode_Join *pJoin = (SWQLNode_Join *) pRoot;
  7931. /* The parse tree is left-heavy and looks like this:
  7932. JN Join node
  7933. / \ / \
  7934. JP OC JoinPair OnClause
  7935. / \ / \
  7936. TR TR TableRef TableRef
  7937. */
  7938. // First, get the first table & prop.
  7939. // ==================================
  7940. SWQLNode_JoinPair *pPair = (SWQLNode_JoinPair *) pJoin->m_pLeft;
  7941. if (!pPair || pPair->m_dwNodeType != TYPE_SWQLNode_JoinPair)
  7942. return WBEM_E_INVALID_QUERY;
  7943. SWQLNode_TableRef *pT1 = (SWQLNode_TableRef *) pPair->m_pLeft;
  7944. SWQLNode_TableRef *pT2 = (SWQLNode_TableRef *) pPair->m_pRight;
  7945. if (!pT1 || !pT2)
  7946. return WBEM_E_INVALID_QUERY;
  7947. SWQLNode_OnClause *pOC = (SWQLNode_OnClause *) pJoin->m_pRight;
  7948. if (!pOC)
  7949. return WBEM_E_INVALID_QUERY;
  7950. SWQLNode_RelExpr *pRE = (SWQLNode_RelExpr *) pOC->m_pLeft;
  7951. if (!pRE)
  7952. return WBEM_E_INVALID_QUERY;
  7953. if (pRE->m_dwExprType != WQL_TOK_TYPED_EXPR)
  7954. return WBEM_E_INVALID_QUERY;
  7955. // We now have the table names available and the matching condition.
  7956. // ==================================================================
  7957. LPWSTR pszClass = pRE->m_pTypedExpr->m_pTableRef;
  7958. LPWSTR pszProp = pRE->m_pTypedExpr->m_pColRef;
  7959. LPWSTR pszClass2 = pRE->m_pTypedExpr->m_pJoinTableRef;
  7960. LPWSTR pszProp2 = pRE->m_pTypedExpr->m_pJoinColRef;
  7961. if (wbem_wcsicmp(pT1->m_pTableName, pszClass) != 0)
  7962. pszClass = pT1->m_pAlias;
  7963. if (wbem_wcsicmp(pT2->m_pTableName, pszClass2) != 0)
  7964. pszClass2 = pT2->m_pAlias;
  7965. if (pszClass == 0 || pszProp == 0 || pszClass2 == 0 || pszProp2 == 0)
  7966. return WBEM_E_INVALID_QUERY;
  7967. pszRetClass1.reset(Macro_CloneLPWSTR(pszClass));
  7968. if (NULL == pszRetClass1.get()) return WBEM_E_OUT_OF_MEMORY;
  7969. pszRetProp1.reset(Macro_CloneLPWSTR(pszProp));
  7970. if (NULL == pszRetProp1.get()) return WBEM_E_OUT_OF_MEMORY;
  7971. pszRetClass2.reset(Macro_CloneLPWSTR(pszClass2));
  7972. if (NULL == pszRetClass2.get()) return WBEM_E_OUT_OF_MEMORY;
  7973. pszRetProp2.reset(Macro_CloneLPWSTR(pszProp2));
  7974. if (NULL ==pszRetProp2.get()) return WBEM_E_OUT_OF_MEMORY;
  7975. return WBEM_S_NO_ERROR;
  7976. }
  7977. //***************************************************************************
  7978. //
  7979. // CWbemNamespace::BuildRuleBasedPathToInst
  7980. //
  7981. // Based on the incoming info, computes the path to the would-be other
  7982. // endpoint.
  7983. //
  7984. // <pEp> The known endpoint.
  7985. // <pszJoinProp1> The property in <pEp> which matches the property in the
  7986. // unknown EP.
  7987. // <pEp2> Class for the other endpoint.
  7988. // <pszJoinProp2> The property in the other class which matches the
  7989. // <pszJoinProp1> in the known endpoint class.
  7990. // <wsNewPath> The proposed path to the instance of class <pEp2>. Who
  7991. // knows whether or not we will find it, but we can try.
  7992. //
  7993. //***************************************************************************
  7994. //
  7995. HRESULT CWbemNamespace::BuildRuleBasedPathToInst(
  7996. IWbemClassObject *pEp,
  7997. LPWSTR pszJoinProp1,
  7998. IWbemClassObject *pEp2,
  7999. LPWSTR pszJoinProp2,
  8000. OUT WString &wsNewPath
  8001. )
  8002. {
  8003. HRESULT hRes;
  8004. // Get the property from the <pEp> which is the cause of all the fuss.
  8005. // ===================================================================
  8006. _variant_t vProp;
  8007. hRes = pEp->Get(pszJoinProp1, 0, &vProp, 0, 0);
  8008. if (FAILED(hRes))
  8009. return hRes;
  8010. _variant_t vClass2;
  8011. hRes = pEp2->Get(L"__CLASS", 0, &vClass2, 0, 0);
  8012. if (FAILED(hRes)) return hRes;
  8013. if (VT_BSTR != V_VT(&vClass2)) return WBEM_E_INVALID_PARAMETER;
  8014. wsNewPath = V_BSTR(&vClass2);
  8015. wsNewPath += L".";
  8016. wsNewPath += pszJoinProp2;
  8017. wsNewPath += L"=";
  8018. // Note 98: Doesn't work for compound keys!! Yuck.
  8019. // ===============================================
  8020. _variant_t vDest;
  8021. hRes = VariantChangeType(&vDest, &vProp, 0, VT_BSTR);
  8022. if (FAILED(hRes)) return hRes;
  8023. wsNewPath += V_BSTR(&vDest);
  8024. return hRes;
  8025. }
  8026. //***************************************************************************
  8027. //
  8028. // CWbemNamespace::ManufactureAssocs
  8029. //
  8030. // Manufactures the associations based on the rule in the <pszJoinQuery>
  8031. // which was extracted from the <rulebased> qualifier. Queries the two
  8032. // endpoint classes and joins the instances to produce the associations
  8033. //
  8034. // <pAssocClass> The association class definition which contains the rule.
  8035. // <pEp> Optional endpoint object. If not NULL, only objects
  8036. // which associate to this endpoint will be returned in
  8037. // the triad list, typically a single object.
  8038. // <pCtx> Call context
  8039. // <pszJoinQuery> The rule query text
  8040. // <aTriads> Receives the output, an array of SAssocTriad pointers.
  8041. // Caller must call SAssocTriad::ArrayCleanup.
  8042. //
  8043. //***************************************************************************
  8044. HRESULT CWbemNamespace::ManufactureAssocs(
  8045. IN IWbemClassObject *pAssocClass,
  8046. IN IWbemClassObject *pEp, // Optional
  8047. IN IWbemContext *pCtx,
  8048. IN LPWSTR pszJoinQuery,
  8049. OUT CFlexArray &aTriads
  8050. )
  8051. {
  8052. HRESULT hRes;
  8053. WString q1, q2;
  8054. CFlexArray aEp1List;
  8055. OnDelete<CFlexArray &,void(*)(CFlexArray &),EmptyObjectList> EmptyMe1(aEp1List);
  8056. CFlexArray aEp2List;
  8057. OnDelete<CFlexArray &,void(*)(CFlexArray &),EmptyObjectList> EmptyMe2(aEp2List);
  8058. wmilib::auto_buffer<WCHAR> pClassName1;
  8059. wmilib::auto_buffer<WCHAR> pClassName2;
  8060. wmilib::auto_buffer<WCHAR> pszJoinProp1;
  8061. wmilib::auto_buffer<WCHAR> pszJoinProp2;
  8062. wmilib::auto_buffer<WCHAR> pszAssocRef1;
  8063. wmilib::auto_buffer<WCHAR> pszAssocRef2;
  8064. _IWmiQuery *pQuery = 0;
  8065. // Parse the query.
  8066. // ================
  8067. CCoreServices *pSvc = CCoreServices::CreateInstance();
  8068. if (NULL == pSvc) return WBEM_E_OUT_OF_MEMORY;
  8069. CReleaseMe rmSvc(pSvc);
  8070. hRes = pSvc->CreateQueryParser(0, &pQuery);
  8071. if (FAILED(hRes)) return hRes;
  8072. CReleaseMe rmQuery(pQuery);
  8073. hRes = pQuery->Parse(L"SQL", pszJoinQuery, 0);
  8074. if (FAILED(hRes)) return hRes;
  8075. // Extract the endpoint class names.
  8076. // ==================================
  8077. hRes = ExtractEpInfoFromQuery(pQuery, pClassName1,pszJoinProp1, pClassName2, pszJoinProp2);
  8078. if (FAILED(hRes)) return hRes;
  8079. // Get the endpoint class defs.
  8080. // ============================
  8081. IWbemClassObject *pClsDef1 = 0;
  8082. hRes = InternalGetClass(pClassName1.get(), &pClsDef1);
  8083. if (FAILED(hRes)) return hRes;
  8084. CReleaseMe rmCls1(pClsDef1);
  8085. IWbemClassObject *pClsDef2 = 0;
  8086. hRes = InternalGetClass(pClassName2.get(), &pClsDef2);
  8087. if (FAILED(hRes)) return hRes;
  8088. CReleaseMe rmCls2(pClsDef2);
  8089. // Map which assoc ref properties point to which class.
  8090. // ====================================================
  8091. hRes = MapAssocRefsToClasses(pAssocClass, pClsDef1, pClsDef2, pszAssocRef1, pszAssocRef2);
  8092. if (FAILED(hRes)) return hRes;
  8093. // If no specific endpoint, an enumeration is requested. We query the endpoint
  8094. // classes completely and match everything up.
  8095. // ============================================================================
  8096. IWbemClassObject *pEp2 = 0;
  8097. CReleaseMeRef<IWbemClassObject *> rmRefEp2(pEp2);
  8098. if (pEp == 0)
  8099. {
  8100. // Build the queries.
  8101. // ===================
  8102. q1 = "select * from ";
  8103. q1 += pClassName1.get();
  8104. q2 = "select * from ";
  8105. q2 += pClassName2.get();
  8106. hRes = ExecSyncQuery(q1, pCtx, 0, aEp1List);
  8107. if (FAILED(hRes)) return hRes;
  8108. hRes = ExecSyncQuery(q2, pCtx, 0, aEp2List);
  8109. if (FAILED(hRes)) return hRes;
  8110. }
  8111. else
  8112. {
  8113. // Note 99: Oversimplified in that it doesn't do an enum; assumes a 1:1 mapping.
  8114. // Compute the path to the other endpoint based on the rule.
  8115. // =============================================================================
  8116. WString wsNewPath;
  8117. hRes = BuildRuleBasedPathToInst(pEp, pszJoinProp1.get(), pClsDef2, pszJoinProp2.get(), wsNewPath); // throws
  8118. if (FAILED(hRes)) return hRes;
  8119. // Do a get object.
  8120. // ================
  8121. hRes = InternalGetInstance(wsNewPath, &pEp2);
  8122. if (FAILED(hRes)) return hRes;
  8123. if (CFlexArray::no_error != aEp1List.Add(pEp)) return WBEM_E_OUT_OF_MEMORY;
  8124. pEp->AddRef();
  8125. if (CFlexArray::no_error != aEp2List.Add(pEp2)) return WBEM_E_OUT_OF_MEMORY;
  8126. pEp2->AddRef();
  8127. }
  8128. // Now, match up the results.
  8129. // For single-object type scenarios, the arrays simply have one element in them. Ho hum.
  8130. // =====================================================================================
  8131. OnDeleteIf<CFlexArray &,void(*)(CFlexArray &),EmptyObjectList> EmptyMeTriads(aTriads);
  8132. hRes = BuildAssocTriads(
  8133. pAssocClass,
  8134. pClsDef1,
  8135. pClsDef2,
  8136. pszJoinProp1.get(),
  8137. pszJoinProp2.get(),
  8138. pszAssocRef1.get(),
  8139. pszAssocRef2.get(),
  8140. aEp1List,
  8141. aEp2List,
  8142. aTriads // OUT
  8143. );
  8144. if (FAILED(hRes)) return hRes;
  8145. EmptyMeTriads.dismiss();
  8146. return hRes;
  8147. }
  8148. //***************************************************************************
  8149. //
  8150. // CWbemNamespace::GetAceList
  8151. //
  8152. // Retrieves the ACEs associated with this namespace
  8153. //
  8154. // <ppAceList> Flexarray to hold ACE list
  8155. //
  8156. //***************************************************************************
  8157. HRESULT CWbemNamespace::GetAceList(CFlexAceArray** ppAceList)
  8158. {
  8159. HRESULT hRes=S_OK;
  8160. *ppAceList = new CFlexAceArray;
  8161. if (ppAceList==NULL)
  8162. hRes = WBEM_E_OUT_OF_MEMORY;
  8163. else
  8164. {
  8165. // 1. Get security descriptor
  8166. CNtSecurityDescriptor& sd = GetSDRef();
  8167. // 2. Get the DACL
  8168. CNtAcl* pDacl;
  8169. pDacl = sd.GetDacl();
  8170. if ( pDacl==NULL )
  8171. return WBEM_E_OUT_OF_MEMORY;
  8172. CDeleteMe<CNtAcl> dm(pDacl);
  8173. // 3. Loop through DACL
  8174. int iNumAces = pDacl->GetNumAces();
  8175. for ( int i=0; i<iNumAces; i++ )
  8176. {
  8177. CNtAce* Ace;
  8178. Ace = pDacl->GetAce(i);
  8179. if ( Ace == NULL )
  8180. return WBEM_E_OUT_OF_MEMORY;
  8181. (*ppAceList)->Add (Ace);
  8182. }
  8183. }
  8184. return hRes;
  8185. }
  8186. //***************************************************************************
  8187. //
  8188. // CWbemNamespace::PutAceList
  8189. //
  8190. // Puts the ACEs associated with this namespace
  8191. //
  8192. // <ppAceList> Flexarray ACE list
  8193. //
  8194. //***************************************************************************
  8195. HRESULT CWbemNamespace::PutAceList(CFlexAceArray* pFlex)
  8196. {
  8197. SCODE sc = S_OK;
  8198. CNtAcl DestAcl;
  8199. int iNumAces = pFlex->Size();
  8200. for (int i=0; i<iNumAces; i++ )
  8201. {
  8202. if ( DestAcl.AddAce ((CNtAce*) pFlex->GetAt(i)) == FALSE )
  8203. {
  8204. return WBEM_E_INVALID_OBJECT;
  8205. }
  8206. }
  8207. if ( m_sd.SetDacl (&DestAcl) == FALSE )
  8208. return WBEM_E_INVALID_OBJECT;
  8209. sc = StoreSDIntoNamespace(m_pSession, m_pNsHandle, m_sd);
  8210. if ( !FAILED (sc) )
  8211. sc = RecursiveSDMerge();
  8212. return sc;
  8213. }
  8214. //***************************************************************************
  8215. //
  8216. // CWbemNamespace::GetDynamicReferenceClasses
  8217. //
  8218. // Asks the provider subsystem for dynamic association classes.
  8219. //
  8220. //
  8221. //***************************************************************************
  8222. HRESULT CWbemNamespace::GetDynamicReferenceClasses( long lFlags, IWbemContext
  8223. * pCtx, IWbemObjectSink* pSink )
  8224. {
  8225. HRESULT hRes = WBEM_S_NO_ERROR;
  8226. _IWmiProviderAssociatorsHelper* pAssocHelp = NULL;
  8227. if ( m_pProvFact)
  8228. {
  8229. hRes = m_pProvFact->GetClassProvider(
  8230. 0, // lFlags
  8231. pCtx,
  8232. m_wszUserName,
  8233. m_wsLocale,
  8234. m_pThisNamespace,
  8235. 0,
  8236. IID__IWmiProviderAssociatorsHelper,
  8237. (LPVOID *) &pAssocHelp
  8238. );
  8239. CReleaseMe rm( pAssocHelp );
  8240. if ( SUCCEEDED( hRes ) )
  8241. {
  8242. hRes = pAssocHelp->GetReferencesClasses( lFlags, pCtx, pSink );
  8243. }
  8244. if ( FAILED( hRes ) )
  8245. {
  8246. pSink->SetStatus( 0L, hRes, 0L, 0L );
  8247. }
  8248. }
  8249. else
  8250. {
  8251. pSink->SetStatus( 0L, WBEM_S_NO_ERROR, 0L, 0L );
  8252. }
  8253. return hRes;
  8254. }
  8255.