/***************************************************************************** Copyright (c) Microsoft Corporation Module Name: ETQuery.CPP Abstract: This module is intended to have the functionality for EVENTTRIGGERS.EXE with -query parameter. This will Query WMI and shows presently available Event Triggers. Author: Akhil Gokhale 03-Oct.-2000 (Created it) Revision History: ******************************************************************************/ #include "pch.h" #include "ETCommon.h" #include "resource.h" #include "ShowError.h" #include "ETQuery.h" #include "WMI.h" #define DEFAULT_USER L"NT AUTHORITY\\SYSTEM" #define DBL_SLASH L"\\\\"; // Defines local to this file #define SHOW_WQL_QUERY L"select * from __instancecreationevent where" #define QUERY_STRING_AND L"select * from __instancecreationevent where \ targetinstance isa \"win32_ntlogevent\" AND" #define BLANK_LINE L"\n" // *************************************************************************** // Routine Description: // Class default constructor. // // Arguments: // None // Return Value: // None // //*************************************************************************** CETQuery::CETQuery() { // init to defaults m_bNeedDisconnect = FALSE; m_pszServerName = NULL; m_pszUserName = NULL; m_pszPassword = NULL; m_pszFormat = NULL; m_bVerbose = FALSE; m_bNoHeader = FALSE; m_pszEventDesc = NULL; m_pszTask = NULL; m_bNeedPassword = FALSE; m_bUsage = FALSE; m_bQuery = FALSE; m_pWbemLocator = NULL; m_pWbemServices = NULL; m_pAuthIdentity = NULL; m_pObj = NULL; m_pTriggerEventConsumer = NULL; m_pEventFilter = NULL; m_arrColData = NULL; m_pszBuffer = NULL; m_pszEventQuery = NULL; m_pszTaskUserName = NULL; m_bIsCOMInitialize = FALSE; m_hStdHandle = NULL; m_pClass = NULL; m_pInClass = NULL; m_pInInst = NULL; m_pOutInst = NULL; m_lHostNameColWidth = WIDTH_HOSTNAME; m_lTriggerIDColWidth = WIDTH_TRIGGER_ID; m_lETNameColWidth = WIDTH_TRIGGER_NAME; m_lTaskColWidth = WIDTH_TASK; m_lQueryColWidth = WIDTH_EVENT_QUERY; m_lDescriptionColWidth = WIDTH_DESCRIPTION; m_lWQLColWidth = 0; m_lTaskUserName = WIDTH_TASK_USERNAME; } // *************************************************************************** // Routine Description: // Class constructor. // // Arguments: // None // Return Value: // None // //*************************************************************************** CETQuery::CETQuery(LONG lMinMemoryReq,BOOL bNeedPassword) { // init to defaults m_bNeedDisconnect = FALSE; m_pszServerName = NULL; m_pszUserName = NULL; m_pszPassword = NULL; m_pszFormat = NULL; m_bVerbose = FALSE; m_bNoHeader = FALSE; m_pszEventDesc = NULL; m_pszTask = NULL; m_bIsCOMInitialize = FALSE; m_hStdHandle = NULL; m_bNeedPassword = bNeedPassword; m_bUsage = FALSE; m_bQuery = FALSE; m_lMinMemoryReq = lMinMemoryReq; m_pClass = NULL; m_pInClass = NULL; m_pInInst = NULL; m_pOutInst = NULL; m_pWbemLocator = NULL; m_pWbemServices = NULL; m_pAuthIdentity = NULL; m_arrColData = NULL; m_pszBuffer = NULL; m_pObj = NULL; m_pTriggerEventConsumer = NULL; m_pEventFilter = NULL; m_pszTaskUserName = NULL; m_pszEventQuery = NULL; m_lHostNameColWidth = WIDTH_HOSTNAME; m_lTriggerIDColWidth = WIDTH_TRIGGER_ID; m_lETNameColWidth = WIDTH_TRIGGER_NAME; m_lTaskColWidth = WIDTH_TASK; m_lQueryColWidth = WIDTH_EVENT_QUERY; m_lDescriptionColWidth = WIDTH_DESCRIPTION; m_lWQLColWidth = 0; m_lTaskUserName = WIDTH_TASK_USERNAME; } // *************************************************************************** // Routine Description: // Class desctructor. It frees memory which is allocated during instance // creation. // // Arguments: // None // Return Value: // None // //*************************************************************************** CETQuery::~CETQuery() { RELEASE_MEMORY_EX(m_pszServerName); RELEASE_MEMORY_EX(m_pszUserName); RELEASE_MEMORY_EX(m_pszPassword); RELEASE_MEMORY_EX(m_pszFormat); RELEASE_MEMORY_EX(m_pszBuffer); RELEASE_MEMORY_EX(m_pszEventDesc); RELEASE_MEMORY_EX(m_pszTask); RELEASE_MEMORY_EX(m_pszTaskUserName); DESTROY_ARRAY(m_arrColData); SAFE_RELEASE_INTERFACE(m_pWbemLocator); SAFE_RELEASE_INTERFACE(m_pWbemServices); SAFE_RELEASE_INTERFACE(m_pObj); SAFE_RELEASE_INTERFACE(m_pTriggerEventConsumer); SAFE_RELEASE_INTERFACE(m_pEventFilter); SAFE_RELEASE_INTERFACE(m_pClass); SAFE_RELEASE_INTERFACE(m_pInClass); SAFE_RELEASE_INTERFACE(m_pInInst); SAFE_RELEASE_INTERFACE(m_pOutInst); RELEASE_MEMORY_EX(m_pszEventQuery); // Uninitialize COM only when it is initialized. if(m_bIsCOMInitialize == TRUE) { CoUninitialize(); } } // *************************************************************************** // Routine Description: // This function will prepare column structure for DoParseParam Function. // // Arguments: // none // Return Value: // none // *************************************************************************** void CETQuery::PrepareCMDStruct() { // -delete lstrcpy(cmdOptions[ ID_Q_QUERY ].szOption,OPTION_QUERY); cmdOptions[ ID_Q_QUERY ].dwFlags = CP_MAIN_OPTION; cmdOptions[ ID_Q_QUERY ].dwCount = 1; cmdOptions[ ID_Q_QUERY ].dwActuals = 0; cmdOptions[ ID_Q_QUERY ].pValue = &m_bQuery; lstrcpy(cmdOptions[ ID_Q_QUERY ].szValues,NULL_STRING); cmdOptions[ ID_Q_QUERY ].pFunction = NULL; cmdOptions[ ID_Q_QUERY ].pFunctionData = NULL; cmdOptions[ ID_Q_QUERY ].pFunctionData = NULL; // -s (servername) lstrcpy(cmdOptions[ ID_Q_SERVER ].szOption,OPTION_SERVER); cmdOptions[ ID_Q_SERVER ].dwFlags = CP_TYPE_TEXT|CP_VALUE_MANDATORY; cmdOptions[ ID_Q_SERVER ].dwCount = 1; cmdOptions[ ID_Q_SERVER ].dwActuals = 0; cmdOptions[ ID_Q_SERVER ].pValue = m_pszServerName; lstrcpy(cmdOptions[ ID_Q_SERVER ].szValues,NULL_STRING); cmdOptions[ ID_Q_SERVER ].pFunction = NULL; cmdOptions[ ID_Q_SERVER ].pFunctionData = NULL; // -u (username) lstrcpy(cmdOptions[ ID_Q_USERNAME ].szOption,OPTION_USERNAME); cmdOptions[ ID_Q_USERNAME ].dwFlags = CP_TYPE_TEXT|CP_VALUE_MANDATORY; cmdOptions[ ID_Q_USERNAME ].dwCount = 1; cmdOptions[ ID_Q_USERNAME ].dwActuals = 0; cmdOptions[ ID_Q_USERNAME ].pValue = m_pszUserName; lstrcpy(cmdOptions[ ID_Q_USERNAME ].szValues,NULL_STRING); cmdOptions[ ID_Q_USERNAME ].pFunction = NULL; cmdOptions[ ID_Q_USERNAME ].pFunctionData = NULL; // -p (password) lstrcpy(cmdOptions[ ID_Q_PASSWORD ].szOption,OPTION_PASSWORD); cmdOptions[ ID_Q_PASSWORD ].dwFlags = CP_TYPE_TEXT|CP_VALUE_OPTIONAL; cmdOptions[ ID_Q_PASSWORD ].dwCount = 1; cmdOptions[ ID_Q_PASSWORD ].dwActuals = 0; cmdOptions[ ID_Q_PASSWORD ].pValue = m_pszPassword; lstrcpy(cmdOptions[ ID_Q_PASSWORD ].szValues,NULL_STRING); cmdOptions[ ID_Q_PASSWORD ].pFunction = NULL; cmdOptions[ ID_Q_PASSWORD ].pFunctionData = NULL; // -fo lstrcpy(cmdOptions[ ID_Q_FORMAT].szOption,OPTION_FORMAT); cmdOptions[ ID_Q_FORMAT].dwFlags = CP_TYPE_TEXT|CP_VALUE_MANDATORY| CP_MODE_VALUES; cmdOptions[ ID_Q_FORMAT].dwCount = 1; cmdOptions[ ID_Q_FORMAT].dwActuals = 0; cmdOptions[ ID_Q_FORMAT].pValue = m_pszFormat; lstrcpy(cmdOptions[ID_Q_FORMAT].szValues,GetResString(IDS_FORMAT_OPTIONS)); cmdOptions[ ID_Q_FORMAT].pFunction = NULL; cmdOptions[ ID_Q_FORMAT].pFunctionData = NULL; // -nh lstrcpy(cmdOptions[ ID_Q_NOHEADER].szOption,OPTION_NOHEADER); cmdOptions[ ID_Q_NOHEADER].dwFlags = 0; cmdOptions[ ID_Q_NOHEADER].dwCount = 1; cmdOptions[ ID_Q_NOHEADER].dwActuals = 0; cmdOptions[ ID_Q_NOHEADER].pValue = &m_bNoHeader; lstrcpy(cmdOptions[ ID_Q_NOHEADER].szValues,NULL_STRING); cmdOptions[ ID_Q_NOHEADER].pFunction = NULL; cmdOptions[ ID_Q_NOHEADER].pFunctionData = NULL; // verbose lstrcpy(cmdOptions[ ID_Q_VERBOSE].szOption,OPTION_VERBOSE); cmdOptions[ ID_Q_VERBOSE ].dwFlags = 0; cmdOptions[ ID_Q_VERBOSE ].dwCount = 1; cmdOptions[ ID_Q_VERBOSE ].dwActuals = 0; cmdOptions[ ID_Q_VERBOSE ].pValue = &m_bVerbose; cmdOptions[ ID_Q_VERBOSE ].pFunction = NULL; cmdOptions[ ID_Q_VERBOSE ].pFunctionData = NULL; } // *************************************************************************** // Routine Description: // This function will process/parce the command line options. // // Arguments: // [ in ] argc : argument(s) count specified at the command prompt // [ in ] argv : argument(s) specified at the command prompt // // Return Value: // TRUE : On Successful // FALSE : On Error // // *************************************************************************** void CETQuery::ProcessOption(DWORD argc, LPCTSTR argv[]) { // local variable BOOL bReturn = TRUE; CHString szTempString; PrepareCMDStruct (); // init the password variable with '*' if ( m_pszPassword != NULL ) lstrcpy( m_pszPassword, _T( "*" ) ); // do the actual parsing of the command line arguments and check the result bReturn = DoParseParam( argc, argv, MAX_COMMANDLINE_Q_OPTION, cmdOptions ); if(bReturn==FALSE) throw CShowError(MK_E_SYNTAX); // empty Server is not valid szTempString = m_pszServerName; szTempString.TrimRight(); lstrcpy(m_pszServerName,(LPCWSTR)szTempString); if ( (cmdOptions[ID_Q_SERVER].dwActuals != 0) && (lstrlen( m_pszServerName) == 0 )) { throw CShowError(IDS_ERROR_SERVERNAME_EMPTY); } // "-u" should not be specified without "-s" if ( cmdOptions[ ID_Q_SERVER ].dwActuals == 0 && cmdOptions[ ID_Q_USERNAME ].dwActuals != 0 ) { throw CShowError(IDS_ERROR_USERNAME_BUT_NOMACHINE); } // empty user is not valid szTempString = m_pszUserName; szTempString.TrimRight(); lstrcpy(m_pszUserName,(LPCWSTR)szTempString); if ( (cmdOptions[ID_Q_USERNAME].dwActuals != 0) && (lstrlen( m_pszUserName) == 0 )) { throw CShowError(IDS_ERROR_USERNAME_EMPTY); } // "-p" should not be specified without -u if ( (cmdOptions[ID_Q_USERNAME].dwActuals == 0) && (cmdOptions[ID_Q_PASSWORD].dwActuals != 0 )) { // invalid syntax throw CShowError(IDS_USERNAME_REQUIRED); } // check whether caller should accept the password or not // if user has specified -s (or) -u and no "-p", then utility should accept // password the user will be prompter for the password only if establish // connection is failed without the credentials information if ( cmdOptions[ ID_Q_PASSWORD ].dwActuals != 0 && m_pszPassword != NULL && lstrcmp( m_pszPassword, _T( "*" ) ) == 0 ) { // user wants the utility to prompt for the password before trying to connect m_bNeedPassword = TRUE; } else if ( cmdOptions[ ID_Q_PASSWORD ].dwActuals == 0 && ( cmdOptions[ ID_Q_SERVER ].dwActuals != 0 || cmdOptions[ ID_Q_USERNAME ].dwActuals != 0 ) ) { // -s, -u is specified without password ... // utility needs to try to connect first and if it fails then prompt for the password m_bNeedPassword = TRUE; if ( m_pszPassword != NULL ) { lstrcpy( m_pszPassword, _T( "" ) ); } } if((m_bNoHeader == TRUE) && ((lstrcmpi(m_pszFormat,GetResString(IDS_STRING_LIST))==0))) { throw CShowError(IDS_HEADER_NOT_ALLOWED); } } // *************************************************************************** // Routine Description: // This function will allocate memory to variables and also checks it and // fills variable with value ZERO. // // Arguments: // None // Return Value: // None // //*************************************************************************** void CETQuery::Initialize() { // local variable LONG lTemp = 0; // if at all any occurs, we know that is 'coz of the // failure in memory allocation ... so set the error SetLastError( E_OUTOFMEMORY ); SaveLastError(); // allocate memory at least MAX_COMPUTER_NAME_LENGTH+1 (its windows ) // constant lTemp = (m_lMinMemoryReq>MAX_COMPUTERNAME_LENGTH)? m_lMinMemoryReq:MAX_COMPUTERNAME_LENGTH+1; m_pszServerName = new TCHAR[lTemp+1]; CheckAndSetMemoryAllocation (m_pszServerName,lTemp); // allocate memory at least MAX_USERNAME_LENGTH+1 (its windows ) // constant lTemp = (m_lMinMemoryReq>MAX_USERNAME_LENGTH)? m_lMinMemoryReq:MAX_USERNAME_LENGTH+1; m_pszUserName = new TCHAR[lTemp+1]; CheckAndSetMemoryAllocation (m_pszUserName,lTemp); // Allocate memory for Run As Username m_pszTaskUserName = new TCHAR[MAX_RES_STRING+1]; CheckAndSetMemoryAllocation(m_pszTaskUserName,MAX_RES_STRING); // allocate memory at least MAX_PASSWORD_LENGTH+1 (its windows ) // constant lTemp = (m_lMinMemoryReq>MAX_PASSWORD_LENGTH)? m_lMinMemoryReq:MAX_PASSWORD_LENGTH+1; m_pszPassword = new TCHAR[lTemp+1]; CheckAndSetMemoryAllocation (m_pszPassword,lTemp); m_pszFormat = new TCHAR[MAX_RES_STRING+1]; CheckAndSetMemoryAllocation (m_pszFormat,MAX_RES_STRING); m_pszBuffer = new TCHAR[(MAX_RES_STRING*4)+1]; CheckAndSetMemoryAllocation (m_pszBuffer,(MAX_RES_STRING*4)); m_pszEventDesc = new TCHAR[(m_lDescriptionColWidth)+1]; CheckAndSetMemoryAllocation (m_pszEventDesc,(m_lDescriptionColWidth)); m_pszEventQuery = new TCHAR[(m_lQueryColWidth)+1]; CheckAndSetMemoryAllocation (m_pszEventQuery,(m_lQueryColWidth)); m_pszTask = new TCHAR[(m_lTaskColWidth)+1]; CheckAndSetMemoryAllocation (m_pszTask,(m_lTaskColWidth)); m_arrColData = CreateDynamicArray(); if(m_arrColData==NULL) { throw CShowError(E_OUTOFMEMORY); } // initialization is successful SetLastError( NOERROR ); // clear the error SetReason( NULL_STRING ); // clear the reason } // *************************************************************************** // Routine Description: // Function will allocate memory to a string // // Arguments: // [in][out] pszStr : String variable to which memory to be allocated // [in] : Number of bytes to be allocated. // Return Value: // NONE // //*************************************************************************** void CETQuery::CheckAndSetMemoryAllocation(LPTSTR pszStr, LONG lSize) { if(pszStr == NULL) { throw CShowError(E_OUTOFMEMORY); } // init to ZERO's ZeroMemory( pszStr, lSize * sizeof( TCHAR ) ); return; } // *************************************************************************** // Routine Description: // This function will execute query. This will enumerate classes from WMI // to get required data. // // Arguments: // None // Return Value: // None // //*************************************************************************** BOOL CETQuery::ExecuteQuery() { // Local variables HRESULT hr = S_OK; // Holds values returned by COM functions BOOL bReturn = TRUE; // status of Return value of this function. BOOL bSearchNTEventLogConsumer = FALSE;//status whether searching in all //instances of NTEventLogConsumer is //successful or not BOOL bSearchEventFilter = FALSE;// status whether searching in all // instances of EventFilter is successful //or not DWORD dwFormatType; // stores FORMAT status values to show results // COM related pointer variable. their usage is well understood by their //names. IEnumWbemClassObject *pEnumFilterToConsumerBinding = NULL; IWbemServices *pLocatorTriggerEventConsumer = NULL; VARIANT vVariant; // variable used to get values from COM functions // Variables to store query results.... TCHAR szHostName[MAX_RES_STRING+1]; TCHAR szEventTriggerName[MAX_RES_STRING+1]; DWORD dwEventId = 0; DWORD dwRowCount = 0; // store Row number. BOOL bAtLeastOneEvent = FALSE; LPTSTR pstrTemp1 = NULL; BSTR bstrConsumer = NULL; BSTR bstrFilter = NULL; BSTR bstrCmdTrigger = NULL; LONG lTemp = 0; try { m_hStdHandle = GetStdHandle(STD_ERROR_HANDLE); if(m_hStdHandle!=NULL) { GetConsoleScreenBufferInfo(m_hStdHandle,&m_ScreenBufferInfo); } InitializeCom(&m_pWbemLocator); m_bIsCOMInitialize = TRUE; { CHString szTempUser = m_pszUserName; // Temp. variabe to store user // name. CHString szTempPassword = m_pszPassword;// Temp. variable to store // password. m_bLocalSystem = TRUE; // Connect remote / local WMI. BOOL bResult = ConnectWmiEx( m_pWbemLocator, &m_pWbemServices, m_pszServerName, szTempUser, szTempPassword, &m_pAuthIdentity, m_bNeedPassword, WMI_NAMESPACE_CIMV2, &m_bLocalSystem); if(bResult == FALSE) { TCHAR szErrorMsg[MAX_RES_STRING+1]; DISPLAY_MESSAGE2( stderr, szErrorMsg, L"%s %s", TAG_ERROR, GetReason()); return FALSE; } // check the remote system version and its compatiblity if ( m_bLocalSystem == FALSE ) { DWORD dwVersion = 0; dwVersion = GetTargetVersionEx( m_pWbemServices, m_pAuthIdentity ); if ( dwVersion <= 5000 ) // to block win2k versions { TCHAR szErrorMsg[MAX_RES_STRING+1]; SetReason( ERROR_OS_INCOMPATIBLE ); DISPLAY_MESSAGE2( stderr, szErrorMsg, L"%s %s", TAG_ERROR, GetReason()); return FALSE; } } // check the local credentials and if need display warning if ( m_bLocalSystem && (lstrlen(m_pszUserName)!=0) ) { CHString str; WMISaveError( WBEM_E_LOCAL_CREDENTIALS ); str.Format( L"%s %s", TAG_WARNING, GetReason() ); ShowMessage( stdout, str ); } } // Show wait message............... m_hStdHandle = GetStdHandle(STD_ERROR_HANDLE); if(m_hStdHandle!=NULL) { GetConsoleScreenBufferInfo(m_hStdHandle,&m_ScreenBufferInfo); } PrintProgressMsg(m_hStdHandle,GetResString(IDS_MSG_EVTRIG_Q),m_ScreenBufferInfo); //Following method will creates an enumerator that returns the // instances of a specified __FilterToConsumerBinding class bstrConsumer = SysAllocString(CLS_FILTER_TO_CONSUMERBINDING); hr = m_pWbemServices-> CreateInstanceEnum(bstrConsumer, WBEM_FLAG_SHALLOW, NULL, &pEnumFilterToConsumerBinding); SAFE_RELEASE_BSTR(bstrConsumer); ON_ERROR_THROW_EXCEPTION(hr); hr = SetInterfaceSecurity( pEnumFilterToConsumerBinding, m_pAuthIdentity ); ON_ERROR_THROW_EXCEPTION(hr); // retrieves CmdTriggerConsumer class bstrCmdTrigger = SysAllocString(CLS_TRIGGER_EVENT_CONSUMER); hr = m_pWbemServices->GetObject(bstrCmdTrigger, 0, NULL, &m_pClass, NULL); RELEASE_BSTR(bstrCmdTrigger); ON_ERROR_THROW_EXCEPTION(hr); // Gets information about the "QueryETrigger( " method of // "cmdTriggerConsumer" class bstrCmdTrigger = SysAllocString(FN_QUERY_ETRIGGER); hr = m_pClass->GetMethod(bstrCmdTrigger, 0, &m_pInClass, NULL); RELEASE_BSTR(bstrCmdTrigger); ON_ERROR_THROW_EXCEPTION(hr); // create a new instance of a class "TriggerEventConsumer ". hr = m_pInClass->SpawnInstance(0, &m_pInInst); ON_ERROR_THROW_EXCEPTION(hr); while(1) { ULONG uReturned = 0; // holds no. of object returns from Next //mathod BSTR bstrTemp = NULL; CHString strTemp; // set the security at the interface level also hr = SetInterfaceSecurity( pEnumFilterToConsumerBinding, m_pAuthIdentity ); ON_ERROR_THROW_EXCEPTION(hr); // Get one object starting at the current position in an //enumeration hr = pEnumFilterToConsumerBinding->Next(WBEM_INFINITE, 1,&m_pObj,&uReturned); ON_ERROR_THROW_EXCEPTION(hr); if(uReturned == 0) { SAFE_RELEASE_INTERFACE(m_pObj); break; } VariantInit(&vVariant); SAFE_RELEASE_BSTR(bstrTemp); bstrTemp = SysAllocString(L"Consumer"); hr = m_pObj->Get(bstrTemp, 0, &vVariant, 0, 0); SAFE_RELEASE_BSTR(bstrTemp); ON_ERROR_THROW_EXCEPTION(hr); bstrConsumer =SysAllocString( vVariant.bstrVal); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); // Search for trggereventconsumer string as we are interested to // get object from this class only strTemp = bstrConsumer; if(strTemp.Find(CLS_TRIGGER_EVENT_CONSUMER)==-1) continue; hr = SetInterfaceSecurity( m_pWbemServices, m_pAuthIdentity ); ON_ERROR_THROW_EXCEPTION(hr); hr = m_pWbemServices->GetObject(bstrConsumer, 0, NULL, &m_pTriggerEventConsumer, NULL); SAFE_RELEASE_BSTR(bstrConsumer); if(FAILED(hr)) { if(hr==WBEM_E_NOT_FOUND) continue; ON_ERROR_THROW_EXCEPTION(hr); } bstrTemp = SysAllocString(L"Filter"); hr = m_pObj->Get(bstrTemp, 0, &vVariant, 0, 0); SAFE_RELEASE_BSTR(bstrTemp); ON_ERROR_THROW_EXCEPTION(hr); bstrFilter = SysAllocString(vVariant.bstrVal); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); hr = m_pWbemServices->GetObject( bstrFilter, 0, NULL, &m_pEventFilter, NULL); SAFE_RELEASE_BSTR(bstrFilter); if(FAILED(hr)) { if(hr==WBEM_E_NOT_FOUND) continue; ON_ERROR_THROW_EXCEPTION(hr); } //retrieves the 'TriggerID' value if exits bstrTemp = SysAllocString(FPR_TRIGGER_ID); hr = m_pTriggerEventConsumer->Get(bstrTemp, 0, &vVariant, 0, 0); if(FAILED(hr)) { if(hr==WBEM_E_NOT_FOUND) continue; ON_ERROR_THROW_EXCEPTION(hr); } SAFE_RELEASE_BSTR(bstrTemp); dwEventId = vVariant.lVal ; hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); //retrieves the 'Action' value if exits bstrTemp = SysAllocString(L"Action"); hr = m_pTriggerEventConsumer->Get(bstrTemp, 0, &vVariant, 0, 0); ON_ERROR_THROW_EXCEPTION(hr); SAFE_RELEASE_BSTR(bstrTemp); lstrcpy(m_pszBuffer,(_TCHAR*)_bstr_t(vVariant.bstrVal)); lTemp = lstrlen(m_pszBuffer); lTemp += 4; // for the safer size for allocation of memory. // allocates memory only if new task length is greate than previous one. if(lTemp > m_lTaskColWidth) { // first free it (if previously allocated) RELEASE_MEMORY_EX(m_pszTask); m_pszTask = new TCHAR[lTemp+1]; CheckAndSetMemoryAllocation(m_pszTask,lTemp); } lstrcpy(m_pszTask,m_pszBuffer); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); //retrieves the 'TriggerDesc' value if exits bstrTemp = SysAllocString(FPR_TRIGGER_DESC); hr = m_pTriggerEventConsumer->Get(bstrTemp, 0, &vVariant, 0, 0); ON_ERROR_THROW_EXCEPTION(hr); SAFE_RELEASE_BSTR(bstrTemp); lstrcpy(m_pszBuffer,(_TCHAR*)_bstr_t(vVariant.bstrVal)); lTemp = lstrlen(m_pszBuffer); if(lTemp == 0)// Means description is not available make it N/A. { lstrcpy(m_pszBuffer,GetResString(IDS_ID_NA)); lTemp = lstrlen(m_pszBuffer); } lTemp += 4; // for the safer size for allocation of memory. // allocates memory only if new Description length is greate than // previous one. if(lTemp > m_lDescriptionColWidth) { // first free it (if previously allocated) RELEASE_MEMORY_EX(m_pszEventDesc); m_pszEventDesc = new TCHAR[lTemp+1]; CheckAndSetMemoryAllocation(m_pszEventDesc,lTemp); } lstrcpy(m_pszEventDesc,m_pszBuffer); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); // TriggerName //retrieves the 'TriggerName' value if exits bstrTemp = SysAllocString(FPR_TRIGGER_NAME); hr = m_pTriggerEventConsumer->Get(bstrTemp, 0, &vVariant, 0, 0); ON_ERROR_THROW_EXCEPTION(hr); SAFE_RELEASE_BSTR(bstrTemp); wsprintf(szEventTriggerName,_T("%s"),vVariant.bstrVal); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); // Host Name //retrieves the '__SERVER' value if exits bstrTemp = SysAllocString(L"__SERVER"); hr = m_pTriggerEventConsumer->Get(bstrTemp, 0, &vVariant, 0, 0); ON_ERROR_THROW_EXCEPTION(hr); SAFE_RELEASE_BSTR(bstrTemp); wsprintf(szHostName,_T("%s"),vVariant.bstrVal); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); bstrTemp = SysAllocString(L"Query"); hr = m_pEventFilter->Get(bstrTemp, 0, &vVariant, 0, 0); SAFE_RELEASE_BSTR(bstrTemp); ON_ERROR_THROW_EXCEPTION(hr); lstrcpy(m_pszBuffer,(_TCHAR*)_bstr_t(vVariant.bstrVal)); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); FindAndReplace(&m_pszBuffer,QUERY_STRING_AND,SHOW_WQL_QUERY); FindAndReplace(&m_pszBuffer,L"targetinstance.LogFile",L"Log"); FindAndReplace(&m_pszBuffer,L"targetinstance.Type",L"Type"); FindAndReplace(&m_pszBuffer,L"targetinstance.EventCode",L"Id"); FindAndReplace(&m_pszBuffer, L"targetinstance.SourceName",L"Source"); FindAndReplace(&m_pszBuffer,L" ",L" ");//to remove extra spaces FindAndReplace(&m_pszBuffer,L" ",L" ");//to remove extra spaces lTemp = lstrlen(m_pszBuffer); lTemp += 4; // for the safer size for allocation of memory. // allocates memory only if new WQL is greate than previous one. if(lTemp > m_lWQLColWidth) { // first free it (if previously allocated) RELEASE_MEMORY_EX(m_pszEventQuery); m_pszEventQuery = new TCHAR[lTemp+1]; CheckAndSetMemoryAllocation(m_pszEventQuery,lTemp); } lTemp = m_lWQLColWidth; CalcColWidth(lTemp,&m_lWQLColWidth,m_pszBuffer); // Now manipulate the WQL string to get EventQuery.... FindAndReplace(&m_pszBuffer,SHOW_WQL_QUERY, GetResString(IDS_EVENTS_WITH)); FindAndReplace(&m_pszBuffer,L" ",L" ");//to remove extra spaces FindAndReplace(&m_pszBuffer,L" ",L" ");//to remove extra spaces lstrcpy(m_pszEventQuery,m_pszBuffer); // Retrieves the "TaskScheduler" information bstrTemp = SysAllocString(L"ScheduledTaskName"); hr = m_pTriggerEventConsumer->Get(bstrTemp, 0, &vVariant, 0, 0); ON_ERROR_THROW_EXCEPTION(hr); SAFE_RELEASE_BSTR(bstrTemp); GetRunAsUserName((LPCWSTR)_bstr_t(vVariant.bstrVal)); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); ////////////////////////////////////////// // Now Shows the results on screen // Appends for in m_arrColData array dwRowCount = DynArrayAppendRow( m_arrColData, NO_OF_COLUMNS ); // Fills Results in m_arrColData data structure DynArraySetString2(m_arrColData,dwRowCount,HOST_NAME,szHostName,0); DynArraySetDWORD2(m_arrColData ,dwRowCount,TRIGGER_ID,dwEventId); DynArraySetString2(m_arrColData,dwRowCount,TRIGGER_NAME,szEventTriggerName,0); DynArraySetString2(m_arrColData,dwRowCount,TASK,m_pszTask,0); DynArraySetString2(m_arrColData,dwRowCount,EVENT_QUERY,m_pszEventQuery,0); DynArraySetString2(m_arrColData,dwRowCount,EVENT_DESCRIPTION,m_pszEventDesc,0); DynArraySetString2(m_arrColData,dwRowCount,TASK_USERNAME,m_pszTaskUserName,0); bAtLeastOneEvent = TRUE; // Calculatate new column width for each column lTemp = m_lHostNameColWidth; CalcColWidth(lTemp,&m_lHostNameColWidth,szHostName); lTemp = m_lETNameColWidth; CalcColWidth(lTemp,&m_lETNameColWidth,szEventTriggerName); lTemp = m_lTaskColWidth; CalcColWidth(lTemp,&m_lTaskColWidth,m_pszTask); lTemp = m_lQueryColWidth; CalcColWidth(lTemp,&m_lQueryColWidth,m_pszEventQuery); lTemp = m_lDescriptionColWidth; CalcColWidth(lTemp,&m_lDescriptionColWidth,m_pszEventDesc); // Resets current containts..if any lstrcpy((szHostName),NULL_STRING); dwEventId = 0; lstrcpy((szEventTriggerName),NULL_STRING); lstrcpy((m_pszTask),NULL_STRING); lstrcpy((m_pszEventQuery),NULL_STRING); lstrcpy((m_pszEventDesc),NULL_STRING); SAFE_RELEASE_INTERFACE(m_pObj); SAFE_RELEASE_INTERFACE(m_pTriggerEventConsumer); SAFE_RELEASE_INTERFACE(m_pEventFilter); } // End of while if(StringCompare(m_pszFormat,GetResString(IDS_STRING_TABLE),TRUE,5)==0) { dwFormatType = SR_FORMAT_TABLE; } else if (StringCompare(m_pszFormat,GetResString(IDS_STRING_LIST), TRUE,4)==0) { dwFormatType = SR_FORMAT_LIST; } else if (StringCompare(m_pszFormat,GetResString(IDS_STRING_CSV), TRUE,3)==0) { dwFormatType = SR_FORMAT_CSV; } else // Default { dwFormatType = SR_FORMAT_TABLE; } if(m_bNoHeader == TRUE) { dwFormatType |=SR_NOHEADER; } PrintProgressMsg(m_hStdHandle,NULL_STRING,m_ScreenBufferInfo); if(bAtLeastOneEvent==TRUE) { // Show Final Query Results on screen PrepareColumns (); ShowMessage(stdout,BLANK_LINE); ShowResults(NO_OF_COLUMNS,mainCols,dwFormatType,m_arrColData); } else { // Show Message ShowMessage(stdout,GetResString(IDS_NO_EVENT_FOUNT)); } } catch(_com_error &e) { TCHAR szErrorMsg[MAX_RES_STRING+1]; PrintProgressMsg(m_hStdHandle,NULL_STRING,m_ScreenBufferInfo); if(hr == 0x80041002)// WMI returns string for this hr value is // "Not Found." which is not user friendly. So // changing the message text. { ShowMessage( stderr,GetResString(IDS_CLASS_NOT_REG)); } else { DISPLAY_MESSAGE2( stderr, szErrorMsg, L"%s %s" , TAG_ERROR, GetReason() ); } return FALSE; } return TRUE; } // *************************************************************************** // Routine Description: // This function will prepare/fill structure which will be used to show // output data. // // Arguments: // None // Return Value: // None // //*************************************************************************** void CETQuery::PrepareColumns() { // local variable // If non verbose output, some column should be hide. DWORD dwMask = m_bVerbose?0:SR_HIDECOLUMN; // For non verbose mode output, column width is predefined else // use dynamically calculated column width. m_lETNameColWidth = m_bVerbose?m_lETNameColWidth:V_WIDTH_TRIG_NAME; m_lTaskColWidth = m_bVerbose?m_lTaskColWidth:V_WIDTH_TASK; m_lTriggerIDColWidth = m_bVerbose?m_lTriggerIDColWidth:V_WIDTH_TRIG_ID; lstrcpy(mainCols[HOST_NAME].szColumn,COL_HOSTNAME); mainCols[HOST_NAME].dwWidth = m_lHostNameColWidth; if(m_bVerbose==TRUE) mainCols[HOST_NAME].dwFlags = SR_TYPE_STRING; else mainCols[HOST_NAME].dwFlags = SR_HIDECOLUMN|SR_TYPE_STRING; lstrcpy(mainCols[HOST_NAME].szFormat,L"%s"); mainCols[HOST_NAME].pFunction = NULL; mainCols[HOST_NAME].pFunctionData = NULL; lstrcpy(mainCols[TRIGGER_ID].szColumn,COL_TRIGGER_ID); mainCols[TRIGGER_ID].dwWidth = m_lTriggerIDColWidth; mainCols[TRIGGER_ID].dwFlags = SR_TYPE_NUMERIC; lstrcpy(mainCols[TRIGGER_ID].szFormat,L"%d"); mainCols[TRIGGER_ID].pFunction = NULL; mainCols[TRIGGER_ID].pFunctionData = NULL; lstrcpy(mainCols[TRIGGER_NAME].szColumn,COL_TRIGGER_NAME); mainCols[TRIGGER_NAME].dwWidth = m_lETNameColWidth; mainCols[TRIGGER_NAME].dwFlags = SR_TYPE_STRING; lstrcpy(mainCols[TRIGGER_NAME].szFormat,L"%s"); mainCols[TRIGGER_NAME].pFunction = NULL; mainCols[TRIGGER_NAME].pFunctionData = NULL; lstrcpy(mainCols[TASK].szColumn,COL_TASK); mainCols[TASK].dwWidth = m_lTaskColWidth; mainCols[TASK].dwFlags = SR_TYPE_STRING; lstrcpy(mainCols[TASK].szFormat,L"%s"); mainCols[TASK].pFunction = NULL; mainCols[TASK].pFunctionData = NULL; lstrcpy(mainCols[EVENT_QUERY].szColumn,COL_EVENT_QUERY); mainCols[EVENT_QUERY].dwWidth = m_lQueryColWidth; if(m_bVerbose==TRUE) mainCols[EVENT_QUERY].dwFlags = SR_TYPE_STRING; else mainCols[EVENT_QUERY].dwFlags = SR_HIDECOLUMN|SR_TYPE_STRING; lstrcpy(mainCols[EVENT_QUERY].szFormat,L"%s"); mainCols[EVENT_QUERY].pFunction = NULL; mainCols[EVENT_QUERY].pFunctionData = NULL; lstrcpy(mainCols[EVENT_DESCRIPTION].szColumn,COL_DESCRIPTION); mainCols[EVENT_DESCRIPTION].dwWidth = m_lDescriptionColWidth; if(m_bVerbose == TRUE) mainCols[EVENT_DESCRIPTION].dwFlags = SR_TYPE_STRING; else mainCols[EVENT_DESCRIPTION].dwFlags = SR_HIDECOLUMN|SR_TYPE_STRING; // Task Username lstrcpy(mainCols[TASK_USERNAME].szFormat,L"%s"); mainCols[TASK_USERNAME].pFunction = NULL; mainCols[TASK_USERNAME].pFunctionData = NULL; lstrcpy(mainCols[TASK_USERNAME].szColumn,COL_TASK_USERNAME); mainCols[TASK_USERNAME].dwWidth = m_lTaskUserName; if(m_bVerbose == TRUE) mainCols[TASK_USERNAME].dwFlags = SR_TYPE_STRING; else mainCols[TASK_USERNAME].dwFlags = SR_HIDECOLUMN|SR_TYPE_STRING; lstrcpy(mainCols[TASK_USERNAME].szFormat,L"%s"); mainCols[TASK_USERNAME].pFunction = NULL; mainCols[TASK_USERNAME].pFunctionData = NULL; } /****************************************************************************** Routine Description: This function Will Find a string (lpszFind) in source string (lpszSource) and replace it with replace string (lpszReplace) for all occurences. Arguments: [in/out] lpszSource : String on which Find-Replace operation to be performed [in] lpszFind : String to be find [in] lpszReplace : String to be replaced. Return Value: 0 - if Unsucessful else returns length of lpszSource. ******************************************************************************/ LONG CETQuery::FindAndReplace(LPTSTR *lpszSource, LPCTSTR lpszFind, LPCTSTR lpszReplace) { LONG lSourceLen = lstrlen(lpszFind); LONG lReplacementLen = lstrlen(lpszReplace); LONG lMainLength = lstrlen(*lpszSource); LPTSTR pszMainSafe= new TCHAR[lstrlen(*lpszSource)+1]; // loop once to figure out the size of the result string LONG nCount = 0; LPTSTR lpszStart = NULL; lpszStart = *lpszSource; LPTSTR lpszEnd = NULL; lpszEnd = lpszStart + lMainLength; LPTSTR lpszTarget=NULL; if ((lSourceLen == 0)||(pszMainSafe==NULL)) { RELEASE_MEMORY_EX(pszMainSafe); return 0; } while (lpszStart < lpszEnd) { while ((lpszTarget = _tcsstr(lpszStart, lpszFind)) != NULL) { nCount++; lpszStart = lpszTarget + lSourceLen; } lpszStart += lstrlen(lpszStart) + 1; } // if any changes were made, make them if (nCount > 0) { lstrcpy(pszMainSafe,*lpszSource); LONG lOldLength = lMainLength; // if the buffer is too small, just // allocate a new buffer (slow but sure) int nNewLength = lMainLength + (lReplacementLen-lSourceLen)*nCount; if(lMainLength < nNewLength) { if(*lpszSource!=NULL) { delete *lpszSource; } *lpszSource = new TCHAR[ (nNewLength*sizeof(TCHAR))+sizeof(TCHAR)]; if( *lpszSource == NULL ) { RELEASE_MEMORY_EX(pszMainSafe); return 0; } memcpy((LPTSTR)*lpszSource,pszMainSafe, lMainLength*sizeof(TCHAR)); } // else, we just do it in-place lpszStart= *lpszSource; lpszEnd = lpszStart +lstrlen(*lpszSource); // loop again to actually do the work while (lpszStart < lpszEnd) { while ( (lpszTarget = _tcsstr(lpszStart, lpszFind)) != NULL) { #ifdef _WIN64 __int64 lBalance ; #else LONG lBalance; #endif lBalance = lOldLength - (lpszTarget - lpszStart + lSourceLen); memmove(lpszTarget + lReplacementLen, lpszTarget + lSourceLen, (size_t) lBalance * sizeof(TCHAR)); memcpy(lpszTarget, lpszReplace, lReplacementLen*sizeof(TCHAR)); lpszStart = lpszTarget + lReplacementLen; lpszStart[lBalance] = NULL_CHAR; lOldLength += (lReplacementLen - lSourceLen); } lpszStart += lstrlen(lpszStart) + 1; } } RELEASE_MEMORY_EX(pszMainSafe); return lstrlen(*lpszSource); } /****************************************************************************** Routine Description: Calculates the width required for column Arguments: [in] lOldLength : Previous length [out] plNewLength : New Length [in] pszString : String . Return Value: none ******************************************************************************/ void CETQuery::CalcColWidth(LONG lOldLength,LONG *plNewLength,LPTSTR pszString) { LONG lStrLength = lstrlen(pszString)+2; //Any way column width should not be greater than MAX_COL_LENGTH // Stores the maximum of WQL length. if(lStrLength > lOldLength) *plNewLength = lStrLength; else *plNewLength = lOldLength; } /****************************************************************************** Routine Description: Get User Name from Task Scheduler Arguments: [in] pszTaskName : Task Name Return Value: HRESULT ******************************************************************************/ HRESULT CETQuery::GetRunAsUserName(LPCWSTR pszScheduleTaskName) { // if pszSheduleTaskName is null or 0 length just return N/A. HRESULT hr = S_OK; BSTR bstrTemp = NULL; VARIANT vVariant; if(lstrlen(pszScheduleTaskName)==0) { lstrcpy(m_pszTaskUserName,DEFAULT_USER); return S_OK; } lstrcpy(m_pszTaskUserName,GetResString(IDS_ID_NA)); // Put input parameter for QueryETrigger method hr = PropertyPut(m_pInInst,FPR_TASK_SCHEDULER,_bstr_t(pszScheduleTaskName)); ON_ERROR_THROW_EXCEPTION(hr); // All The required properties sets, so // executes DeleteETrigger method to delete eventtrigger hr = m_pWbemServices->ExecMethod(_bstr_t(CLS_TRIGGER_EVENT_CONSUMER), _bstr_t(FN_QUERY_ETRIGGER), 0, NULL, m_pInInst,&m_pOutInst,NULL); ON_ERROR_THROW_EXCEPTION(hr); bstrTemp = SysAllocString(FPR_RUN_AS_USER); VariantInit(&vVariant); hr = m_pOutInst->Get(bstrTemp, 0, &vVariant, 0, 0); SAFE_RELEASE_BSTR(bstrTemp); ON_ERROR_THROW_EXCEPTION(hr); wsprintf(m_pszTaskUserName,_T("%s"),vVariant.bstrVal); hr = VariantClear(&vVariant); ON_ERROR_THROW_EXCEPTION(hr); if(lstrlen(m_pszTaskUserName)==0) { lstrcpy(m_pszTaskUserName,GetResString(IDS_ID_NA)); } return S_OK; }