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.

442 lines
10 KiB

  1. #include "precomp.h"
  2. #include <stdio.h>
  3. #include <assert.h>
  4. #include "fconnspc.h"
  5. LPCWSTR g_wszConsumer = L"Consumer";
  6. LPWSTR g_wszTarget = L"Target";
  7. LPWSTR g_wszQueued = L"Queued";
  8. LPWSTR g_wszTargetUsed = L"TargetUsed";
  9. LPCWSTR g_wszStatusCode = L"StatusCode";
  10. LPCWSTR g_wszExecutionId = L"ExecutionId";
  11. LPWSTR g_wszTraceClass = L"MSFT_FCExecutedTraceEvent";
  12. LPWSTR g_wszTargetTraceClass = L"MSFT_FCTargetTraceEvent";
  13. LPWSTR g_wszEvents = L"Events";
  14. LPCWSTR g_wszTraceProvider
  15. = L"Microsoft WMI Forwarding Consumer Trace Event Provider";
  16. LPCWSTR g_wszTraceSuccessQuery =
  17. L"SELECT * FROM MSFT_FCTraceEventBase WHERE StatusCode <= 1";
  18. LPCWSTR g_wszTraceFailureQuery =
  19. L"SELECT * FROM MSFT_FCTraceEventBase WHERE StatusCode > 1";
  20. /**************************************************************************
  21. CFwdConsQuerySink - this implements the ProviderQuerySink. This would
  22. normally be implemented by CFwdConsNamespace, but we'd end up with a
  23. circular reference on the DES.
  24. ****************************************************************************/
  25. class CFwdConsQuerySink
  26. : public CUnkBase<IWbemEventProviderQuerySink,&IID_IWbemEventProviderQuerySink>
  27. {
  28. CFwdConsNamespace* m_pNspc; // doesn't hold ref.
  29. public:
  30. STDMETHOD(NewQuery)( DWORD dwId, LPWSTR wszLanguage, LPWSTR wszQuery )
  31. {
  32. return m_pNspc->NewQuery( dwId, wszQuery );
  33. }
  34. STDMETHOD(CancelQuery)( DWORD dwId )
  35. {
  36. return m_pNspc->CancelQuery( dwId );
  37. }
  38. CFwdConsQuerySink( CFwdConsNamespace* pNspc )
  39. : CUnkBase< IWbemEventProviderQuerySink,
  40. &IID_IWbemEventProviderQuerySink>(NULL), m_pNspc( pNspc ) {}
  41. public:
  42. static HRESULT Create( CFwdConsNamespace* pNspc,
  43. IWbemEventProviderQuerySink** ppSink )
  44. {
  45. CWbemPtr<IWbemEventProviderQuerySink> pSink;
  46. pSink = new CFwdConsQuerySink( pNspc );
  47. if ( pSink == NULL )
  48. {
  49. return WBEM_E_OUT_OF_MEMORY;
  50. }
  51. pSink->AddRef();
  52. *ppSink = pSink;
  53. return WBEM_S_NO_ERROR;
  54. }
  55. };
  56. CFwdConsNamespace::~CFwdConsNamespace()
  57. {
  58. if ( m_pDES != NULL )
  59. {
  60. m_pDES->UnRegister();
  61. }
  62. }
  63. HRESULT CFwdConsNamespace::InitializeTraceEventBase( IWbemClassObject* pTrace,
  64. HRESULT hres,
  65. CFwdContext* pCtx )
  66. {
  67. HRESULT hr;
  68. VARIANT var;
  69. V_VT(&var) = VT_UNKNOWN;
  70. V_UNKNOWN(&var) = pCtx->m_pCons;
  71. hr = pTrace->Put( g_wszConsumer, 0, &var, NULL );
  72. if ( FAILED(hr) )
  73. {
  74. return hr;
  75. }
  76. WCHAR achExecutionId[64];
  77. if ( StringFromGUID2( pCtx->m_guidExecution, achExecutionId, 64 ) == 0 )
  78. {
  79. return WBEM_E_CRITICAL_ERROR;
  80. }
  81. V_VT(&var) = VT_BSTR;
  82. V_BSTR(&var) = achExecutionId;
  83. hr = pTrace->Put( g_wszExecutionId, 0, &var, NULL );
  84. if ( FAILED(hr) )
  85. {
  86. return hr;
  87. }
  88. V_VT(&var) = VT_I4;
  89. V_I4(&var) = hres;
  90. return pTrace->Put( g_wszStatusCode, 0, &var, NULL );
  91. }
  92. //
  93. // called after each execution of a forwarding consumer.
  94. //
  95. HRESULT CFwdConsNamespace::HandleTrace( HRESULT hres, CFwdContext* pCtx )
  96. {
  97. HRESULT hr;
  98. CWbemPtr<IWbemEventSink> pTraceSink;
  99. if ( SUCCEEDED(hres) )
  100. {
  101. if ( m_pTraceSuccessSink->IsActive() == WBEM_S_FALSE )
  102. {
  103. return WBEM_S_NO_ERROR;
  104. }
  105. else
  106. {
  107. pTraceSink = m_pTraceSuccessSink;
  108. }
  109. }
  110. else if ( m_pTraceFailureSink->IsActive() == WBEM_S_FALSE )
  111. {
  112. return WBEM_S_NO_ERROR;
  113. }
  114. else
  115. {
  116. pTraceSink = m_pTraceFailureSink;
  117. }
  118. CWbemPtr<IWbemClassObject> pTrace;
  119. hr = m_pTraceClass->SpawnInstance( 0, &pTrace );
  120. if ( FAILED(hr) )
  121. {
  122. return hr;
  123. }
  124. hr = InitializeTraceEventBase( pTrace, hres, pCtx );
  125. if ( FAILED(hr) )
  126. {
  127. return hr;
  128. }
  129. //
  130. // set the events that were indicated in the trace event
  131. //
  132. VARIANT var;
  133. V_VT(&var) = VT_ARRAY | VT_UNKNOWN;
  134. V_ARRAY(&var) = SafeArrayCreateVector( VT_UNKNOWN, 0, pCtx->m_cEvents );
  135. if ( V_ARRAY(&var) == NULL )
  136. {
  137. return WBEM_E_OUT_OF_MEMORY;
  138. }
  139. {
  140. CPropSafeArray<IUnknown*> apEvents(V_ARRAY(&var));
  141. for( ULONG i=0; i < pCtx->m_cEvents; i++ )
  142. {
  143. apEvents[i] = pCtx->m_apEvents[i];
  144. apEvents[i]->AddRef();
  145. }
  146. }
  147. hr = pTrace->Put( g_wszEvents, 0, &var, NULL );
  148. VariantClear( &var );
  149. if ( FAILED(hr) )
  150. {
  151. return hr;
  152. }
  153. //
  154. // don't set other props on failure.
  155. //
  156. if ( FAILED(hres) )
  157. {
  158. return pTraceSink->Indicate( 1, &pTrace );
  159. }
  160. //
  161. // it is possible that there may be not target.
  162. //
  163. if ( pCtx->m_wsTarget.Length() > 0 )
  164. {
  165. LPWSTR wszTarget = pCtx->m_wsTarget;
  166. V_VT(&var) = VT_BSTR;
  167. V_BSTR(&var) = wszTarget;
  168. hr = pTrace->Put( g_wszTargetUsed, 0, &var, NULL );
  169. if ( FAILED(hr) )
  170. {
  171. return hr;
  172. }
  173. }
  174. V_VT(&var) = VT_BOOL;
  175. V_BOOL(&var) = pCtx->m_bQueued ? VARIANT_TRUE : VARIANT_FALSE;
  176. hr = pTrace->Put( g_wszQueued, 0, &var, NULL );
  177. if ( FAILED(hr) )
  178. {
  179. return hr;
  180. }
  181. return pTraceSink->Indicate( 1, &pTrace );
  182. }
  183. //
  184. // This is called by Senders when their SendReceive() method is called for
  185. // both error and success states. In both cases the wszTrace string will
  186. // be the name of the sender. Senders, such as the multisender or fwdsender
  187. // can call the sink multiple times since they can represent multiple
  188. // connections. Since all Senders initialize themselves lazily, we don't
  189. // have to worry about generating trace events when Open() calls fail.
  190. //
  191. STDMETHODIMP CFwdConsNamespace::Notify( HRESULT hres,
  192. GUID guidSource,
  193. LPCWSTR wszTrace,
  194. IUnknown* pContext )
  195. {
  196. HRESULT hr;
  197. //
  198. // since we are the ones who created the context, we can safely cast.
  199. //
  200. CFwdContext* pCtx = (CFwdContext*)pContext;
  201. if ( SUCCEEDED(hres) )
  202. {
  203. //
  204. // save any state with the context about the successful send.
  205. //
  206. if ( guidSource == CLSID_WmiMessageMsmqSender )
  207. {
  208. pCtx->m_bQueued = TRUE;
  209. }
  210. pCtx->m_wsTarget = wszTrace;
  211. }
  212. CWbemPtr<IWbemEventSink> pTraceSink;
  213. if ( SUCCEEDED(hres) )
  214. {
  215. if ( m_pTraceSuccessSink->IsActive() == WBEM_S_FALSE )
  216. {
  217. return WBEM_S_NO_ERROR;
  218. }
  219. else
  220. {
  221. pTraceSink = m_pTraceSuccessSink;
  222. }
  223. }
  224. else if ( m_pTraceFailureSink->IsActive() == WBEM_S_FALSE )
  225. {
  226. return WBEM_S_NO_ERROR;
  227. }
  228. else
  229. {
  230. pTraceSink = m_pTraceFailureSink;
  231. }
  232. CWbemPtr<IWbemClassObject> pTrace;
  233. hr = m_pTargetTraceClass->SpawnInstance( 0, &pTrace );
  234. if ( FAILED(hr) )
  235. {
  236. return hr;
  237. }
  238. hr = InitializeTraceEventBase( pTrace, hres, pCtx );
  239. if ( FAILED(hr) )
  240. {
  241. return hr;
  242. }
  243. LPWSTR wszTmp = LPWSTR(wszTrace);
  244. VARIANT var;
  245. V_VT(&var) = VT_BSTR;
  246. V_BSTR(&var) = wszTmp;
  247. hr = pTrace->Put( g_wszTarget, 0, &var, NULL );
  248. if ( FAILED(hr) )
  249. {
  250. return hr;
  251. }
  252. return pTraceSink->Indicate( 1, &pTrace );
  253. }
  254. HRESULT CFwdConsNamespace::Initialize( LPCWSTR wszNamespace )
  255. {
  256. HRESULT hr;
  257. m_wsName = wszNamespace;
  258. //
  259. // register our decoupled event provider
  260. //
  261. hr = CoCreateInstance( CLSID_WbemDecoupledBasicEventProvider,
  262. NULL,
  263. CLSCTX_INPROC_SERVER,
  264. IID_IWbemDecoupledBasicEventProvider,
  265. (void**)&m_pDES );
  266. if ( FAILED(hr) )
  267. {
  268. return hr;
  269. }
  270. hr = m_pDES->Register( 0,
  271. NULL,
  272. NULL,
  273. NULL,
  274. wszNamespace,
  275. g_wszTraceProvider,
  276. NULL );
  277. if ( FAILED(hr) )
  278. {
  279. return hr;
  280. }
  281. //
  282. // get the service pointer for out namespace
  283. //
  284. hr = m_pDES->GetService( 0, NULL, &m_pSvc );
  285. if ( FAILED(hr) )
  286. {
  287. return hr;
  288. }
  289. //
  290. // get the decoupled event sink
  291. //
  292. CWbemPtr<IWbemObjectSink> pTraceObjectSink;
  293. hr = m_pDES->GetSink( 0, NULL, &pTraceObjectSink );
  294. if ( FAILED(hr) )
  295. {
  296. return hr;
  297. }
  298. CWbemPtr<IWbemEventSink> pTraceEventSink;
  299. hr = pTraceObjectSink->QueryInterface( IID_IWbemEventSink,
  300. (void**)&pTraceEventSink);
  301. if ( FAILED(hr) )
  302. {
  303. return WBEM_E_CRITICAL_ERROR;
  304. }
  305. //
  306. // get restricted query for successes.
  307. //
  308. hr = pTraceEventSink->GetRestrictedSink( 1,
  309. &g_wszTraceSuccessQuery,
  310. NULL,
  311. &m_pTraceSuccessSink );
  312. if ( FAILED(hr) )
  313. {
  314. return hr;
  315. }
  316. //
  317. // get restricted query for failures.
  318. //
  319. hr = pTraceEventSink->GetRestrictedSink( 1,
  320. &g_wszTraceFailureQuery,
  321. NULL,
  322. &m_pTraceFailureSink );
  323. if ( FAILED(hr) )
  324. {
  325. return hr;
  326. }
  327. //
  328. // more trace initialization
  329. //
  330. hr = m_pSvc->GetObject( g_wszTraceClass, 0, NULL, &m_pTraceClass, NULL );
  331. if ( FAILED(hr) )
  332. {
  333. return hr;
  334. }
  335. hr = m_pSvc->GetObject( g_wszTargetTraceClass,
  336. 0,
  337. NULL,
  338. &m_pTargetTraceClass,
  339. NULL );
  340. if ( FAILED(hr) )
  341. {
  342. return hr;
  343. }
  344. return WBEM_S_NO_ERROR;
  345. }