Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

455 lines
13 KiB

  1. //***************************************************************************
  2. // Copyright (c) Microsoft Corporation
  3. //
  4. // Module Name:
  5. // TRIGGERCONSUMER.CPP
  6. //
  7. // Abstract:
  8. // Contains CEventConsumer implementation.
  9. //
  10. // Author:
  11. // Vasundhara .G
  12. //
  13. // Revision History:
  14. // Vasundhara .G 9-oct-2k : Created It.
  15. //***************************************************************************
  16. #include "pch.h"
  17. #include "EventConsumerProvider.h"
  18. #include "General.h"
  19. #include "TriggerConsumer.h"
  20. #include "resource.h"
  21. extern HMODULE g_hModule;
  22. #define PROPERTY_COMMAND _T( "Action" )
  23. #define PROPERTY_TRIGID _T( "TriggerID" )
  24. #define PROPERTY_NAME _T( "TriggerName" )
  25. #define PROPERTY_SHEDULE _T( "ScheduledTaskName" )
  26. #define SPACE _T( " " )
  27. #define SLASH _T( "\\" )
  28. #define NEWLINE _T( "\0" )
  29. //***************************************************************************
  30. // Routine Description:
  31. // Constructor for CTriggerConsumer class for initialization.
  32. //
  33. // Arguments:
  34. // None.
  35. //
  36. // Return Value:
  37. // None.
  38. //***************************************************************************
  39. CTriggerConsumer::CTriggerConsumer()
  40. {
  41. // initialize the reference count variable
  42. m_dwCount = 0;
  43. }
  44. //***************************************************************************
  45. // Routine Description:
  46. // Desstructor for CTriggerConsumer class.
  47. //
  48. // Arguments:
  49. // None.
  50. //
  51. // Return Value:
  52. // None.
  53. //***************************************************************************
  54. CTriggerConsumer::~CTriggerConsumer()
  55. {
  56. // there is nothing much to do at this place ...
  57. }
  58. //***************************************************************************
  59. // Routine Description:
  60. // Returns a pointer to a specified interface on an object
  61. // to which a client currently holds an interface pointer.
  62. //
  63. // Arguments:
  64. // riid [in] : Identifier of the interface being requested.
  65. // ppv [out] :Address of pointer variable that receives the
  66. // interface pointer requested in riid. Upon successful
  67. // return, *ppvObject contains the requested interface
  68. // pointer to the object.
  69. //
  70. // Return Value:
  71. // NOERROR if the interface is supported.
  72. // E_NOINTERFACE if not.
  73. //***************************************************************************
  74. STDMETHODIMP CTriggerConsumer::QueryInterface( REFIID riid, LPVOID* ppv )
  75. {
  76. // initialy set to NULL
  77. *ppv = NULL;
  78. // check whether interface requested is one we have
  79. if ( riid == IID_IUnknown || riid == IID_IWbemUnboundObjectSink )
  80. {
  81. //
  82. // yes ... requested interface exists
  83. *ppv = this; // set the out parameter for the returning the requested interface
  84. this->AddRef(); // update the reference count
  85. return NOERROR; // inform success
  86. }
  87. // interface is not available
  88. return E_NOINTERFACE;
  89. }
  90. //***************************************************************************
  91. // Routine Description:
  92. // The AddRef method increments the reference count for
  93. // an interface on an object. It should be called for every
  94. // new copy of a pointer to an interface on a given object.
  95. //
  96. // Arguments:
  97. // none.
  98. //
  99. // Return Value:
  100. // Returns the value of the new reference count.
  101. //***************************************************************************
  102. STDMETHODIMP_(ULONG) CTriggerConsumer::AddRef( void )
  103. {
  104. // increment the reference count ... thread safe
  105. return InterlockedIncrement( ( LPLONG ) &m_dwCount );
  106. }
  107. //***************************************************************************
  108. // Routine Description:
  109. // The Release method decreases the reference count of the object by 1.
  110. //
  111. // Arguments:
  112. // none.
  113. //
  114. // Return Value:
  115. // Returns the new reference count.
  116. //***************************************************************************
  117. STDMETHODIMP_(ULONG) CTriggerConsumer::Release( void )
  118. {
  119. // decrement the reference count ( thread safe ) and check whether
  120. // there are some more references or not ... based on the result value
  121. DWORD dwCount = 0;
  122. dwCount = InterlockedDecrement( ( LPLONG ) &m_dwCount );
  123. if ( dwCount == 0 )
  124. {
  125. // free the current factory instance
  126. delete this;
  127. }
  128. // return the no. of instances references left
  129. return dwCount;
  130. }
  131. //***************************************************************************
  132. // Routine Description:
  133. // IndicateToConsumer method is called by Windows Management
  134. // to actually deliver events to a consumer.
  135. //
  136. // Arguments:
  137. // pLogicalCosumer [in] :Pointer to the logical consumer object
  138. // for which this set of objects is delivered.
  139. // lNumObjects [in] :Number of objects delivered in the array that follows.
  140. // ppObjects [in] : Pointer to an array of IWbemClassObject
  141. // instances which represent the events delivered.
  142. //
  143. // Return Value:
  144. // Returns WBEM_S_NO_ERROR if successful.
  145. // Otherwise error.
  146. //***************************************************************************
  147. STDMETHODIMP CTriggerConsumer::IndicateToConsumer( IWbemClassObject* pLogicalConsumer,
  148. LONG lNumObjects,
  149. IWbemClassObject **ppObjects )
  150. {
  151. STARTUPINFO info;
  152. PROCESS_INFORMATION procinfo;
  153. TCHAR szCommand[ MAX_STRING_LENGTH ] = NULL_STRING;
  154. TCHAR szName[ MAX_STRING_LENGTH ] = NULL_STRING;
  155. TCHAR szTask[ MAX_STRING_LENGTH ] = NULL_STRING;
  156. TCHAR szPath[ MAX_STRING_LENGTH ] = NULL_STRING;
  157. DWORD dwID = 0;
  158. PTCHAR szParams = NULL;
  159. PTCHAR szExe = NULL;
  160. HRESULT hRes = 0;
  161. BOOL bResult = FALSE;
  162. VARIANT varValue;
  163. VARIANT varScheduler;
  164. memset( szCommand, 0, sizeof( szCommand ) );
  165. memset( szName, 0, sizeof( szName ) );
  166. memset( szPath, 0, sizeof( szPath ) );
  167. memset( szTask, 0, sizeof( szTask ) );
  168. // get the 'Item' property values out of the embedded object.
  169. hRes = PropertyGet( pLogicalConsumer, PROPERTY_COMMAND, 0, szCommand, MAX_STRING_LENGTH );
  170. if ( FAILED( hRes ) )
  171. {
  172. return hRes;
  173. }
  174. // get the trigger name.
  175. hRes = PropertyGet( pLogicalConsumer, PROPERTY_NAME, 0, szName, MAX_STRING_LENGTH );
  176. if( FAILED( hRes ) )
  177. return hRes;
  178. VariantInit( &varScheduler );
  179. hRes = pLogicalConsumer->Get( PROPERTY_SHEDULE, 0, &varScheduler, NULL, NULL );
  180. if( FAILED( hRes ) )
  181. return hRes;
  182. try
  183. {
  184. lstrcpyW( szTask, ( LPCWSTR ) _bstr_t( varScheduler ) );
  185. }
  186. catch( ... )
  187. {
  188. // memory exhausted -- return
  189. return E_OUTOFMEMORY;
  190. }
  191. VariantInit( &varValue );
  192. hRes = pLogicalConsumer->Get( PROPERTY_TRIGID, 0, &varValue, NULL, NULL );
  193. if( FAILED( hRes ) )
  194. return hRes;
  195. if( varValue.vt == VT_NULL || varValue.vt == VT_EMPTY )
  196. return WBEM_E_INVALID_PARAMETER;
  197. dwID = varValue.lVal;
  198. VariantClear( &varValue );
  199. if( lstrlen( szTask ) > 0 )
  200. {
  201. try
  202. {
  203. ITaskScheduler *pITaskScheduler = NULL;
  204. IEnumWorkItems *pIEnum = NULL;
  205. IPersistFile *pIPF = NULL;
  206. ITask *pITask = NULL;
  207. LPWSTR *lpwszNames = NULL;
  208. DWORD dwFetchedTasks = 0;
  209. TCHAR szActualTask[MAX_STRING_LENGTH] = NULL_STRING;
  210. pITaskScheduler = GetTaskScheduler();
  211. if ( pITaskScheduler == NULL )
  212. {
  213. hRes = E_FAIL;
  214. ONFAILTHROWERROR( hRes );
  215. }
  216. hRes = pITaskScheduler->Enum( &pIEnum );
  217. ONFAILTHROWERROR( hRes );
  218. while ( SUCCEEDED( pIEnum->Next( 1,
  219. &lpwszNames,
  220. &dwFetchedTasks ) )
  221. && (dwFetchedTasks != 0))
  222. {
  223. while (dwFetchedTasks)
  224. {
  225. // Check whether the TaskName is present, if present
  226. // then return arrJobs.
  227. // Convert the Wide Charater to Multi Byte value.
  228. GetCompatibleStringFromUnicode( lpwszNames[ --dwFetchedTasks ], szActualTask, SIZE_OF_ARRAY( szActualTask ) );
  229. // Parse the TaskName to remove the .job extension.
  230. szActualTask[lstrlen(szActualTask ) - lstrlen(JOB) ] = NULL_CHAR;
  231. StrTrim( szActualTask, TRIM_SPACES );
  232. CHString strTemp;
  233. strTemp = varScheduler.bstrVal;
  234. if( lstrcmpi( szActualTask, strTemp ) == 0 )
  235. {
  236. hRes = pITaskScheduler->Activate( szActualTask, IID_ITask, (IUnknown**) &pITask );
  237. ONFAILTHROWERROR( hRes );
  238. hRes = pITask->Run();
  239. ONFAILTHROWERROR( hRes );
  240. bResult = TRUE;
  241. }
  242. CoTaskMemFree( lpwszNames[ dwFetchedTasks ] );
  243. }//end while
  244. CoTaskMemFree( lpwszNames );
  245. }
  246. pIEnum->Release();
  247. if( bResult == TRUE )
  248. {
  249. HRESULT phrStatus;
  250. Sleep( 10000 );
  251. hRes = pITask->GetStatus( &phrStatus );
  252. ONFAILTHROWERROR( hRes );
  253. switch(phrStatus)
  254. {
  255. case SCHED_S_TASK_READY:
  256. LoadStringW( g_hModule, IDS_TRIGGERED, szTask, MAX_STRING_LENGTH );
  257. break;
  258. case SCHED_S_TASK_RUNNING:
  259. LoadStringW( g_hModule, IDS_TRIGGERED, szTask, MAX_STRING_LENGTH );
  260. break;
  261. case SCHED_S_TASK_NOT_SCHEDULED:
  262. LoadStringW( g_hModule, IDS_TRIGGER_FAILED, szTask, MAX_STRING_LENGTH );
  263. break;
  264. default:
  265. LoadStringW( g_hModule, IDS_TRIGGER_NOT_FOUND, szTask, MAX_STRING_LENGTH );
  266. }
  267. ErrorLog( ( LPCTSTR ) szTask, szName, dwID );
  268. }
  269. else
  270. {
  271. LoadStringW( g_hModule, IDS_TRIGGER_NOT_FOUND, szTask, MAX_STRING_LENGTH );
  272. ErrorLog( ( LPCTSTR ) szTask, szName, dwID );
  273. }
  274. } //try
  275. catch(_com_error& e)
  276. {
  277. IWbemStatusCodeText *pIStatus = NULL;
  278. BSTR bstrErr = NULL;
  279. LPTSTR lpResStr = NULL;
  280. lpResStr = ( LPTSTR ) __calloc( MAX_RES_STRING + 1, sizeof( TCHAR ) );
  281. if ( lpResStr != NULL )
  282. {
  283. if (SUCCEEDED(CoCreateInstance(CLSID_WbemStatusCodeText, 0,
  284. CLSCTX_INPROC_SERVER,
  285. IID_IWbemStatusCodeText,
  286. (LPVOID*) &pIStatus)))
  287. {
  288. if (SUCCEEDED(pIStatus->GetErrorCodeText(e.Error(), 0, 0, &bstrErr)))
  289. {
  290. GetCompatibleStringFromUnicode(bstrErr,lpResStr,wcslen(bstrErr));
  291. }
  292. SAFEBSTRFREE(bstrErr);
  293. LoadStringW( g_hModule, IDS_TRIGGER_FAILED, szTask, MAX_STRING_LENGTH );
  294. LoadStringW( g_hModule, IDS_ERROR_CODE, szCommand, MAX_STRING_LENGTH );
  295. wsprintf( szPath, szCommand, e.Error() );
  296. lstrcat( szTask, szPath );
  297. LoadStringW( g_hModule, IDS_REASON, szCommand, MAX_STRING_LENGTH );
  298. wsprintf( szPath, szCommand, lpResStr );
  299. lstrcat( szTask, szPath );
  300. ErrorLog( ( LPCTSTR ) szTask, szName, dwID );
  301. }
  302. SAFERELEASE(pIStatus);
  303. free( lpResStr );
  304. return( hRes );
  305. }
  306. }//catch
  307. catch( CHeap_Exception )
  308. {
  309. return E_OUTOFMEMORY;
  310. }
  311. } //if
  312. else
  313. {
  314. TCHAR szApplName[ MAX_STRING_LENGTH ] = NULL_STRING;
  315. TCHAR szParams[ MAX_STRING_LENGTH ] = NULL_STRING;
  316. //
  317. // prepare the process start up info
  318. info.cb = sizeof( info );
  319. info.cbReserved2 = 0;
  320. info.dwFillAttribute = 0;
  321. info.dwX = 0;
  322. info.dwXCountChars = 0;
  323. info.dwXSize = 0;
  324. info.dwY = 0;
  325. info.dwYCountChars = 0;
  326. info.dwYSize = 0;
  327. info.hStdError = NULL;
  328. info.hStdInput = NULL;
  329. info.hStdOutput = NULL;
  330. info.lpDesktop = NULL;//( "winsta0\\default" );
  331. info.lpReserved = NULL;
  332. info.lpReserved2 = NULL;
  333. info.lpTitle = NULL;
  334. // init process info structure with 0's
  335. ZeroMemory( &procinfo, sizeof( PROCESS_INFORMATION ) );
  336. bResult = ProcessFilePath( szCommand, szApplName, szParams );
  337. if( bResult == TRUE )
  338. {
  339. if( lstrlen( szParams ) == 0 )
  340. {
  341. bResult = CreateProcess( NULL, szApplName, NULL, NULL,
  342. FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &info,
  343. &procinfo );
  344. }
  345. else
  346. {
  347. bResult = CreateProcess( szApplName, szParams, NULL, NULL,
  348. FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &info,
  349. &procinfo );
  350. }
  351. }
  352. else
  353. {
  354. SetLastError( E_OUTOFMEMORY );
  355. }
  356. if(bResult == 0)
  357. {
  358. LPVOID lpMsgBuf = NULL; // pointer to handle error message
  359. // load the system error message from the windows itself
  360. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  361. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  362. NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  363. (LPTSTR) &lpMsgBuf, 0, NULL );
  364. LoadStringW( g_hModule, IDS_TRIGGER_FAILED, szTask, MAX_STRING_LENGTH );
  365. LoadStringW( g_hModule, IDS_ERROR_CODE, szCommand, MAX_STRING_LENGTH );
  366. wsprintf( szPath, szCommand, GetLastError() );
  367. lstrcat( szTask, szPath );
  368. LoadStringW( g_hModule, IDS_REASON, szCommand, MAX_STRING_LENGTH );
  369. wsprintf( szPath, szCommand, lpMsgBuf );
  370. lstrcat( szTask, szPath );
  371. ErrorLog( ( LPCTSTR ) szTask, szName, dwID );
  372. if ( lpMsgBuf != NULL )
  373. {
  374. LocalFree( lpMsgBuf );
  375. }
  376. return GetLastError();
  377. }
  378. else
  379. {
  380. LoadStringW( g_hModule, IDS_TRIGGERED, szTask, MAX_STRING_LENGTH );
  381. ErrorLog( ( LPCTSTR ) szTask, szName, dwID );
  382. return WBEM_S_NO_ERROR;
  383. }
  384. }
  385. return WBEM_S_NO_ERROR;
  386. }
  387. //***************************************************************************
  388. // Routine Description:
  389. // This routine gets task scheduler interface.
  390. //
  391. // Arguments:
  392. // none.
  393. //
  394. // Return Value:
  395. // Returns ITaskScheduler interface.
  396. //***************************************************************************
  397. ITaskScheduler* CTriggerConsumer::GetTaskScheduler()
  398. {
  399. HRESULT hRes = S_OK;
  400. ITaskScheduler *pITaskScheduler = NULL;
  401. hRes = CoCreateInstance( CLSID_CTaskScheduler, NULL, CLSCTX_ALL,
  402. IID_ITaskScheduler,(LPVOID*) &pITaskScheduler );
  403. if( FAILED(hRes))
  404. {
  405. return NULL;
  406. }
  407. hRes = pITaskScheduler->SetTargetComputer( NULL );
  408. return pITaskScheduler;
  409. }