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.

540 lines
13 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. MERGERREQ.CPP
  5. Abstract:
  6. Implementations of the various merger request classes.
  7. History:
  8. sanjes 28-Feb-01 Created.
  9. --*/
  10. #include "precomp.h"
  11. #pragma warning (disable : 4786)
  12. #include <wbemcore.h>
  13. #include <map>
  14. #include <vector>
  15. #include <genutils.h>
  16. #include <oahelp.inl>
  17. #include <wqllex.h>
  18. #include "wmimerger.h"
  19. #include <helper.h>
  20. //
  21. // Merger Request implementations.
  22. //
  23. CMergerClassReq::CMergerClassReq( CWmiMerger* pMerger, CWmiMergerRecord* pParentRecord,
  24. CWbemNamespace* pNamespace, CBasicObjectSink* pHandler,
  25. IWbemContext* pContext)
  26. : CMergerReq( pNamespace, pHandler, pContext ),
  27. m_pMerger( pMerger ),
  28. m_pParentRecord( pParentRecord ),
  29. m_pSink( pHandler )
  30. {
  31. if ( NULL != m_pMerger )
  32. {
  33. m_pMerger->AddRef();
  34. }
  35. if ( NULL != m_pSink )
  36. {
  37. m_pSink->AddRef();
  38. }
  39. SetForceRun(1);
  40. SetPriority(PriorityForceRunRequests);
  41. }
  42. CMergerClassReq::~CMergerClassReq()
  43. {
  44. if ( NULL != m_pMerger )
  45. {
  46. m_pMerger->Release();
  47. }
  48. if ( NULL != m_pSink )
  49. {
  50. m_pSink->Release();
  51. }
  52. }
  53. void CMergerClassReq::DumpError()
  54. {
  55. // none
  56. }
  57. // Pass off execution to the merger
  58. HRESULT CMergerParentReq::Execute ()
  59. {
  60. try
  61. {
  62. // m_pParentRecord is NULL for the original CMergerParentRquest
  63. //
  64. return m_pMerger->Exec_MergerParentRequest( m_pParentRecord, m_pSink ); // throw
  65. }
  66. catch (CX_MemoryException &)
  67. {
  68. return WBEM_E_OUT_OF_MEMORY;
  69. }
  70. }
  71. HRESULT CMergerChildReq::Execute ()
  72. {
  73. HRESULT hRes = m_pMerger->Exec_MergerChildRequest( m_pParentRecord, m_pSink );
  74. return hRes;
  75. }
  76. // Merger Requests
  77. CMergerDynReq::CMergerDynReq( CWbemObject* pClassDef, CWbemNamespace* pNamespace, IWbemObjectSink* pHandler,
  78. IWbemContext* pContext )
  79. : CMergerReq( pNamespace, pHandler, pContext )
  80. {
  81. HRESULT hr = pClassDef->GetClassName( &m_varClassName );
  82. if ( FAILED( hr ) || m_varClassName.IsNull())
  83. {
  84. throw CX_MemoryException();
  85. }
  86. }
  87. HRESULT CMergerDynReq_DynAux_GetInstances :: Execute ()
  88. {
  89. HRESULT hRes = m_pNamespace->Exec_DynAux_GetInstances (
  90. m_pClassDef ,
  91. m_lFlags ,
  92. m_pContext ,
  93. m_pSink
  94. ) ;
  95. return hRes;
  96. }
  97. void CMergerDynReq_DynAux_GetInstances ::DumpError()
  98. {
  99. // none
  100. }
  101. HRESULT CMergerDynReq_DynAux_ExecQueryAsync :: Execute ()
  102. {
  103. HRESULT hRes = m_pNamespace->Exec_DynAux_ExecQueryAsync (
  104. m_pClassDef ,
  105. m_Query,
  106. m_QueryFormat,
  107. m_lFlags ,
  108. m_pContext ,
  109. m_pSink
  110. ) ;
  111. return hRes;
  112. }
  113. void CMergerDynReq_DynAux_ExecQueryAsync ::DumpError()
  114. {
  115. // none
  116. }
  117. // Static Requests
  118. CMergerDynReq_Static_GetInstances::CMergerDynReq_Static_GetInstances (
  119. CWbemNamespace *pNamespace ,
  120. CWbemObject *pClassDef ,
  121. long lFlags ,
  122. IWbemContext *pCtx ,
  123. CBasicObjectSink *pSink ,
  124. QL_LEVEL_1_RPN_EXPRESSION* pParsedQuery
  125. ) : CMergerDynReq (
  126. pClassDef ,
  127. pNamespace ,
  128. pSink ,
  129. pCtx
  130. ) ,
  131. m_pClassDef(pClassDef),
  132. m_pCtx(pCtx),
  133. m_pSink(pSink),
  134. m_lFlags(lFlags),
  135. m_pParsedQuery( pParsedQuery )
  136. {
  137. if ( m_pParsedQuery )
  138. {
  139. m_pParsedQuery->AddRef();
  140. }
  141. if (m_pClassDef)
  142. {
  143. m_pClassDef->AddRef () ;
  144. }
  145. if (m_pCtx)
  146. {
  147. m_pCtx->AddRef () ;
  148. }
  149. if (m_pSink)
  150. {
  151. m_pSink->AddRef () ;
  152. }
  153. }
  154. CMergerDynReq_Static_GetInstances::~CMergerDynReq_Static_GetInstances ()
  155. {
  156. if (m_pClassDef)
  157. {
  158. m_pClassDef->Release () ;
  159. }
  160. if (m_pCtx)
  161. {
  162. m_pCtx->Release () ;
  163. }
  164. if (m_pSink)
  165. {
  166. m_pSink->Release () ;
  167. }
  168. if ( NULL != m_pParsedQuery )
  169. {
  170. m_pParsedQuery->Release();
  171. }
  172. }
  173. // Calls into the query engine
  174. HRESULT CMergerDynReq_Static_GetInstances::Execute()
  175. {
  176. HRESULT hr = WBEM_E_FAILED;
  177. IWbemClassObject * pErrObj = NULL;
  178. CSetStatusOnMe SetStatusOnMe(m_pSink,hr,pErrObj);
  179. int nRes = CQueryEngine::ExecAtomicDbQuery(
  180. m_pNamespace->GetNsSession(),
  181. m_pNamespace->GetNsHandle(),
  182. m_pNamespace->GetScope(),
  183. GetName(),
  184. m_pParsedQuery,
  185. m_pSink,
  186. m_pNamespace );
  187. if (CQueryEngine::invalid_query == nRes)
  188. hr = WBEM_E_INVALID_QUERY;
  189. else if(0 == nRes)
  190. hr = WBEM_S_NO_ERROR;
  191. return hr;
  192. }
  193. void CMergerDynReq_Static_GetInstances ::DumpError()
  194. {
  195. // none
  196. }
  197. //
  198. // CWmiMergerRequestMgr implementation.
  199. //
  200. CWmiMergerRequestMgr::CWmiMergerRequestMgr( CWmiMerger* pMerger )
  201. : m_pMerger( pMerger ),
  202. m_HierarchyArray(),
  203. m_dwNumRequests( 0 ),
  204. m_dwMinLevel( 0xFFFFFFFF ),
  205. m_dwMaxLevel( 0 )
  206. {
  207. }
  208. CWmiMergerRequestMgr::~CWmiMergerRequestMgr()
  209. {
  210. Clear();
  211. }
  212. // Clears the manager of ALL arrays
  213. HRESULT CWmiMergerRequestMgr::Clear( void )
  214. {
  215. for ( int x = 0; x < m_HierarchyArray.Size(); x++ )
  216. {
  217. CSortedUniquePointerArray<CMergerDynReq>* pArray =
  218. (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[x];
  219. if ( NULL != pArray )
  220. {
  221. delete pArray;
  222. m_HierarchyArray.SetAt( x, NULL );
  223. }
  224. }
  225. // Set to 0
  226. m_dwNumRequests = 0L;
  227. return WBEM_S_NO_ERROR;
  228. }
  229. // Adds a new request to the manager
  230. HRESULT CWmiMergerRequestMgr::AddRequest( CMergerDynReq* pReq, DWORD dwLevel )
  231. {
  232. // Locate the array for the level. If we need to allocate one, do so.
  233. HRESULT hr = WBEM_S_NO_ERROR;
  234. CSortedUniquePointerArray<CMergerDynReq>* pArray = NULL;
  235. // Check first if we have built out to this level, then if so, do we have
  236. // an array for the level.
  237. if ( dwLevel >= m_HierarchyArray.Size() || NULL == m_HierarchyArray[dwLevel] )
  238. {
  239. pArray = new CSortedUniquePointerArray<CMergerDynReq>; // SEC:REVIEWED 2002-03-22 : Needs EH
  240. if ( NULL != pArray )
  241. {
  242. // First, if we're not built out to the required size,
  243. // NULL out the elements from size to our level
  244. if ( dwLevel >= m_HierarchyArray.Size() )
  245. {
  246. for ( int x = m_HierarchyArray.Size(); SUCCEEDED( hr ) && x <= dwLevel; x++ )
  247. {
  248. if ( m_HierarchyArray.Add( NULL ) != CFlexArray::no_error )
  249. {
  250. hr = WBEM_E_OUT_OF_MEMORY;
  251. }
  252. else
  253. {
  254. if ( dwLevel < m_dwMinLevel )
  255. {
  256. m_dwMinLevel = dwLevel;
  257. }
  258. else if ( dwLevel > m_dwMaxLevel )
  259. {
  260. m_dwMaxLevel = dwLevel;
  261. }
  262. }
  263. } // FOR enum elements
  264. } // IF dwLevel >= Array size
  265. if ( SUCCEEDED( hr ) )
  266. {
  267. m_HierarchyArray.SetAt( dwLevel, pArray );
  268. }
  269. if ( FAILED( hr ) )
  270. {
  271. delete pArray;
  272. }
  273. }
  274. else
  275. {
  276. hr = WBEM_E_OUT_OF_MEMORY;
  277. }
  278. }
  279. else
  280. {
  281. // This should NEVER be NULL
  282. pArray = (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[dwLevel];
  283. _DBG_ASSERT( pArray != NULL );
  284. if ( NULL == pArray )
  285. {
  286. hr = WBEM_E_FAILED;
  287. }
  288. }
  289. // Finally, add the request to the array. Subsequent worker threads
  290. // will locate requests and execute them.
  291. if ( SUCCEEDED( hr ) )
  292. {
  293. if ( pArray->Insert( pReq ) < 0 )
  294. {
  295. hr = WBEM_E_OUT_OF_MEMORY;
  296. }
  297. else
  298. {
  299. ++m_dwNumRequests;
  300. }
  301. }
  302. return hr;
  303. }
  304. DWORD CWmiMergerRequestMgr::GetNumRequestsAtLevel( DWORD dwLevel )
  305. {
  306. if ( dwLevel >= m_HierarchyArray.Size() ) return 0;
  307. CSortedUniquePointerArray<CMergerDynReq>* pArray = (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[dwLevel];
  308. if ( NULL == pArray ) return 0;
  309. return pArray->GetSize();
  310. }
  311. //
  312. // this function removes the first request in the array of the requests
  313. // for a given level of the hierarchy
  314. //
  315. ///////////////////////////////////////////////////////////////////////////////////
  316. BOOL CWmiMergerRequestMgr::GetRequestAtLevel( DWORD dwLevel, wmilib::auto_ptr<CMergerReq> & pReq )
  317. {
  318. if ( dwLevel >= m_HierarchyArray.Size() ) return FALSE;
  319. CSortedUniquePointerArray<CMergerDynReq>* pArray = (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[dwLevel];
  320. if ( NULL == pArray ) return FALSE;
  321. if (0 == pArray->GetSize()) return FALSE;
  322. CMergerDynReq * pRealReq = NULL;
  323. pArray->RemoveAt(0,&pRealReq);
  324. pReq.reset(pRealReq);
  325. return TRUE;
  326. }
  327. // Removes a request from the manager and returns it to the caller.
  328. // The caller is responsible for cleaning up the request.
  329. HRESULT CWmiMergerRequestMgr::RemoveRequest( DWORD dwLevel, LPCWSTR pwszName,
  330. wmilib::auto_ptr<CMergerReq> & pReq )
  331. {
  332. // Locate the array for the level.
  333. HRESULT hr = WBEM_S_NO_ERROR;
  334. if ( dwLevel < m_HierarchyArray.Size() )
  335. {
  336. CSortedUniquePointerArray<CMergerDynReq>* pArray =
  337. (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[dwLevel];
  338. // pArray is NULL if the class hierarchy combine static with dynamic
  339. if ( NULL != pArray )
  340. {
  341. int nIndex;
  342. // Under certain race conditions, another thread
  343. // can actually remove a request before one thread
  344. // processes it, so if it's not there, the assumption
  345. // is that it was already removed.
  346. pReq.reset(pArray->Find( pwszName, &nIndex )); // SEC:REVIEWED 2002-03-22 : Should have EH in case <ppReq> is NULL
  347. if ( NULL != pReq.get() )
  348. {
  349. // Now remove the element from the array, the caller
  350. // is responsible for deleting it
  351. pArray->RemoveAtNoDelete( nIndex );
  352. --m_dwNumRequests;
  353. }
  354. else
  355. {
  356. hr = WBEM_E_NOT_FOUND;
  357. }
  358. }
  359. else
  360. {
  361. hr = WBEM_E_FAILED;
  362. }
  363. }
  364. else
  365. {
  366. hr = WBEM_E_FAILED;
  367. }
  368. return hr;
  369. }
  370. HRESULT CWmiMergerRequestMgr::GetTopmostParentReqName( WString& wsClassName )
  371. {
  372. HRESULT hr = WBEM_E_NOT_FOUND;
  373. if ( m_dwNumRequests > 0 )
  374. {
  375. for ( int x = 0; WBEM_E_NOT_FOUND == hr && x < m_HierarchyArray.Size(); x++ )
  376. {
  377. CSortedUniquePointerArray<CMergerDynReq>* pArray =
  378. (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[x];
  379. // The Array must exist and have elements
  380. if ( NULL != pArray && pArray->GetSize() > 0 )
  381. {
  382. // Get the class name from the first request
  383. try
  384. {
  385. wsClassName = pArray->GetAt( 0 )->GetName();
  386. hr = WBEM_S_NO_ERROR;
  387. }
  388. catch(...)
  389. {
  390. ExceptionCounter c;
  391. hr = WBEM_E_OUT_OF_MEMORY;
  392. }
  393. }
  394. } // For enum arrays
  395. }
  396. return hr;
  397. }
  398. BOOL CWmiMergerRequestMgr::HasSingleStaticRequest( void )
  399. {
  400. BOOL fRet = FALSE;
  401. if ( 1 == m_dwNumRequests )
  402. {
  403. HRESULT hr = WBEM_E_NOT_FOUND;
  404. for ( int x = 0; WBEM_E_NOT_FOUND == hr && x < m_HierarchyArray.Size(); x++ )
  405. {
  406. CSortedUniquePointerArray<CMergerDynReq>* pArray =
  407. (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[x];
  408. // The Array must exist and have elements
  409. if ( NULL != pArray && pArray->GetSize() > 0 )
  410. {
  411. // Get the class name from the first request
  412. fRet = pArray->GetAt(0)->IsStatic();
  413. hr = WBEM_S_NO_ERROR;
  414. }
  415. } // For enum arrays
  416. } // Must be 1 and only 1 request
  417. return fRet;
  418. }
  419. #ifdef __DEBUG_MERGER_THROTTLING
  420. void CWmiMergerRequestMgr::DumpRequestHierarchy( void )
  421. {
  422. HRESULT hr = WBEM_E_NOT_FOUND;
  423. if ( m_dwNumRequests > 0 )
  424. {
  425. for ( int x = 0; FAILED( hr ) && x < m_HierarchyArray.Size(); x++ )
  426. {
  427. CSortedUniquePointerArray<CMergerDynReq>* pArray =
  428. (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[x];
  429. // The Array must exist and have elements
  430. if ( NULL != pArray && pArray->GetSize() > 0 )
  431. {
  432. for ( int y = 0; y < pArray->GetSize(); y++ )
  433. {
  434. DbgPrintfA(0,"Merger Request, Level %d, Class Name: %s\n", x, pArray->GetAt(y)->GetName() );
  435. }
  436. }
  437. } // For enum arrays
  438. }
  439. }
  440. #else
  441. void CWmiMergerRequestMgr::DumpRequestHierarchy( void )
  442. {
  443. }
  444. #endif