// CollectionControl.cpp : Defines the entry point for the DLL application. // //*************************************************************************** // // judyp May 1999 // //*************************************************************************** #include "stdafx.h" #pragma warning (disable : 4786) #pragma warning (disable : 4275) #include #include #include #include #include #include #include using namespace std; #include #include #include #ifdef NONNT5 typedef unsigned long ULONG_PTR; #endif #include #include #include #include #include #include "t_string.h" #include "Persistor.h" #include "Logger.h" #include "StructureWrappers.h" #include "StructureWapperHelpers.h" #include "ConstantMap.h" #include "TCOData.h" #include "Utilities.h" #include "CollectionControl.h" extern CConstantMap g_ConstantMap; #if 0 Command line arguments: Must provide at least -action, and -file. -action is one of start, stop, enable, query, update or queryall -file is a single data file. Examples: -file E:\EventTrace\TCODataFiles\ANSI\1-1-1-2.txt -detail E:\EventTrace\TCOLogFiles\ANSI\TestRuns If you are using this framework to drive non-collection control tests use -action scenario. #endif #define ERROR_COULD_NOT_CREATE_PROCESS 10 #define ERROR_COULD_NOT_GET_PROCESS_RETURN 11 #define ERROR_WAIT_FAILED 12 struct ProcessData { // Passed from caller. LPTSTR m_lptstrExePath; LPTSTR m_lptstrCmdLine; LPTSTR m_lptstrTCOId; LPTSTR m_lptstrLogFile; int m_nGuids; LPGUID m_lpguidArray; HANDLE m_hEventContinue; HANDLE m_hEventProcessCompleted; // Filled in by thread that starts the process DWORD m_dwThreadReturn; HANDLE m_hProcess; DWORD m_dwProcessReturn; int m_nSystemError; }; struct StartTraceWithProviderData { TCOData *m_pstructTCOData; TCOFunctionalData *m_pstructTCOFunctionalData; LPTSTR m_lptstrAction; LPTSTR m_lptstrDataFile; LPTSTR m_lptstrDetailPath; LPTSTR m_lptstrTCOTestError; ProcessData *m_pstructProcessData; bool m_bStartConsumers; ProcessData **m_pstructConsumerDataArray; HANDLE *m_handleConsmers; }; void FreeStartTraceWithProviderData(StartTraceWithProviderData *p); void FreeStartTraceWithProviderDataArray(StartTraceWithProviderData **p, int nP); ProcessData *InitializeProcessData ( TCOData *pstructTCOData, TCOFunctionalData *pstructTCOFunctionalData, LPTSTR lptstrDetailPath, int nProcessIndex, bool bProvider ); void FreeProcessData(ProcessData *pProcessData); void FreeProcessDataArray(ProcessData **pProcessData, int nProcessData); void InitializeExeAndCmdLine ( ProcessData *&pstructProcessData, TCOData *pstructTCOData, TCOFunctionalData *pstructTCOFunctionalData, LPTSTR lptstrDetailPath, int nProcessIndex, bool bProvider ); // Just allows the test to be driven programatically in addition to from // the command line. Dispatches based upon lptstrAction. int BeginTCOTest ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, LPTSTR lptstrUpdateDataFile, LPTSTR lptstrProviderExe, bool bLogExpected, bool bUseTraceHandle ); // List of files or single file. int ActionScenario ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected ); int ActionStartTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected ); int ActionStopTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected, bool bUseTraceHandle ); int ActionEnableTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected ); int ActionQueryTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected, bool bUseTraceHandle ); int ActionUpdateTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, LPTSTR lptstrUpdateDataFile, bool bLogExpected, bool bUseTraceHandle ); int ActionQueryAllTraces ( LPTSTR lptstrAction, LPTSTR lptstrDetailPath ); int ActionStartProvider ( LPTSTR lptstrAction, LPTSTR lptstrProviderExe ); int RunActionScenarioWithProvider ( TCOData *pstructTCOData, TCOFunctionalData *pstructTCOFunctionalData, LPTSTR &lptstrAction, LPTSTR &lpctstrDataFile, LPTSTR &lptstrDetailPath, LPTSTR &lptstrTCOTestError ); unsigned int __stdcall RunActionScenarioWithProvider(void *pVoid); int GetArgs ( t_string tsCommandLine, LPTSTR &lptstrAction, LPTSTR &lptstrDataFile, LPTSTR &lptstrDetailPath, LPTSTR &lptstrUpdateDataFile, LPTSTR &lptstrProviderExe, bool &bLogExpected, bool &bUseTraceHandle // QueryTrace, EnableTrace, UpdateTrace, and StopTrace ); int FreeArgs ( LPTSTR &lptstrAction, LPTSTR &lptstrDataFile, LPTSTR &lptstrDetailPath, LPTSTR &lptstrUpdateDataFile, LPTSTR &lptstrProviderExe ); t_string GetTestName(LPTSTR lptstrDataFile); unsigned int __stdcall RunProcess (void * pVoid); void ThreadLogger (int nState, LPCTSTR lptstrFunction, LPCTSTR lptstrMsg, bool bUseULONGValue, ULONG ulValue); CLogger g_ThreadLogger(_T("E:\\EventTrace\\TCOLogFiles\\ThreadLog.txt"), false); // Command line // -action starttrace -file E:\EventTrace\TCODataFiles\unicode\1-1-1-2.txt -detail E:\EventTrace\TCOLogFiles\ANSI\TestRuns #ifdef NT5BUILD __cdecl #else int #endif main(int argc, char* argv[]) { LPTSTR lptstrAction = NULL; LPTSTR lptstrDataFile = NULL; LPTSTR lptstrDetailPath = NULL; LPTSTR lptstrUpdateDataFile = NULL; LPTSTR lptstrProviderExe = NULL; bool bLogExpected = true; bool bUseTraceHandle = false; t_string tsCommandLine; LPTSTR lptstrCommandLine = NewTCHAR (GetCommandLine()); tsCommandLine = lptstrCommandLine; free(lptstrCommandLine); lptstrCommandLine = NULL; int nReturn = GetArgs ( tsCommandLine, lptstrAction, lptstrDataFile, lptstrDetailPath, lptstrUpdateDataFile, lptstrProviderExe, bLogExpected, bUseTraceHandle ); if (nReturn != 0) { t_cout << _T("Command line error with: \n") << tsCommandLine.c_str() << _T(".\n"); FreeArgs ( lptstrAction, lptstrDataFile, lptstrDetailPath, lptstrUpdateDataFile, lptstrProviderExe ); return nReturn; } if (!lptstrDataFile && !(case_insensitive_compare(lptstrAction,_T("queryalltraces")) == 0 || case_insensitive_compare(lptstrAction,_T("providerexe")) == 0 || case_insensitive_compare(lptstrAction,_T("line")) == 0 || case_insensitive_compare(lptstrAction,_T("sleep")) == 0) ) { t_cout << _T("Must provide a data file!\n"); FreeArgs ( lptstrAction, lptstrDataFile, lptstrDetailPath, lptstrUpdateDataFile, lptstrProviderExe ); return -1; } nReturn = BeginTCOTest ( lptstrAction, lptstrDataFile, lptstrDetailPath, lptstrUpdateDataFile, lptstrProviderExe, bLogExpected, bUseTraceHandle ); FreeArgs ( lptstrAction, lptstrDataFile, lptstrDetailPath, lptstrUpdateDataFile, lptstrProviderExe ); return nReturn; } int BeginTCOTest ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, LPTSTR lptstrUpdateDataFile, LPTSTR lptstrProviderExe, bool bLogExpected, bool bUseTraceHandle ) { int nReturn = ERROR_SUCCESS; if (case_insensitive_compare(lptstrAction,_T("scenario")) == 0) { nReturn = ActionScenario ( lptstrAction, lptstrDataFile, lptstrDetailPath, bLogExpected ); } else if (case_insensitive_compare(lptstrAction,_T("starttrace")) == 0) { nReturn = ActionStartTrace ( lptstrAction, lptstrDataFile, lptstrDetailPath, bLogExpected ); } else if (case_insensitive_compare(lptstrAction,_T("stoptrace")) == 0) { nReturn = ActionStopTrace ( lptstrAction, lptstrDataFile, lptstrDetailPath, bLogExpected, bUseTraceHandle ); } else if (case_insensitive_compare(lptstrAction,_T("enabletrace")) == 0) { nReturn = ActionEnableTrace ( lptstrAction, lptstrDataFile, lptstrDetailPath, bLogExpected ); } else if (case_insensitive_compare(lptstrAction,_T("querytrace")) == 0) { nReturn = ActionQueryTrace ( lptstrAction, lptstrDataFile, lptstrDetailPath, bLogExpected, bUseTraceHandle ); } else if (case_insensitive_compare(lptstrAction,_T("updatetrace")) == 0) { // If bUseTraceHandle is true we will start things with the // lptstrDataFile and update with the lptstrUpdateDataFile. // If bUseTraceHandle is false we will update with the // lptstrDataFile. nReturn = ActionUpdateTrace ( lptstrAction, lptstrDataFile, lptstrDetailPath, lptstrUpdateDataFile, bLogExpected, bUseTraceHandle ); } else if (case_insensitive_compare(lptstrAction,_T("queryalltraces")) == 0) { nReturn = ActionQueryAllTraces ( lptstrAction, lptstrDetailPath ); } else if (case_insensitive_compare(lptstrAction,_T("providerexe")) == 0) { nReturn = ActionStartProvider ( lptstrAction, lptstrProviderExe ); } else if (case_insensitive_compare(lptstrAction,_T("sleep")) == 0) { nReturn = ERROR_SUCCESS; Sleep(5000); } else if (case_insensitive_compare(lptstrAction,_T("line")) == 0) { t_cout << _T("\n"); } return nReturn; } int ActionStartTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected ) { int nResult = ERROR_SUCCESS; LPTSTR lptstrTCOTestError = NULL; TCOData *pstructTCOData = NULL; TCOFunctionalData *pstructTCOFunctionalData = NULL; int nAPICallResult = 0; t_string tsDetailFile; nResult = GetAllTCOData ( lptstrDataFile , &pstructTCOData, &pstructTCOFunctionalData, &lptstrTCOTestError ); if (nResult != ERROR_SUCCESS) { t_cout << _T("Could not get TCO Data: ") << lptstrTCOTestError << _T("\n"); FreeTCOData(pstructTCOData); pstructTCOData = NULL; FreeTCOFunctionalData(pstructTCOFunctionalData); pstructTCOFunctionalData = NULL; free(lptstrTCOTestError); lptstrTCOTestError = NULL; return nResult; } tsDetailFile = lptstrDetailPath; tsDetailFile += _T("\\"); tsDetailFile += GetTestName(lptstrDataFile); nResult = StartTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), bLogExpected, pstructTCOData, &nAPICallResult ); tsDetailFile.erase(); FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nResult; } int ActionStopTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected, bool bUseTraceHandle ) { int nResult = ERROR_SUCCESS; LPTSTR lptstrTCOTestError = NULL; TCOData *pstructTCOData = NULL; TCOFunctionalData *pstructTCOFunctionalData = NULL; int nAPICallResult = 0; t_string tsDetailFile; nResult = GetAllTCOData ( lptstrDataFile , &pstructTCOData, &pstructTCOFunctionalData, &lptstrTCOTestError ); if (nResult != ERROR_SUCCESS) { t_cout << _T("Could not get TCO Data: ") << lptstrTCOTestError << _T("\n"); FreeTCOData(pstructTCOData); pstructTCOData = NULL; FreeTCOFunctionalData(pstructTCOFunctionalData); pstructTCOFunctionalData = NULL; free(lptstrTCOTestError); lptstrTCOTestError = NULL; return nResult; } tsDetailFile = lptstrDetailPath; tsDetailFile += _T("\\"); tsDetailFile += GetTestName(lptstrDataFile); t_string tsError; // If bUseTraceHandle is true we will start the logger. if (bUseTraceHandle) { nResult = StartTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), false, pstructTCOData, &nAPICallResult ); if (nResult != ERROR_SUCCESS) { FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nResult; } Sleep(2000); int nResult2 = EnableTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), false, pstructTCOData, &nAPICallResult ); Sleep(5000); // Restore this. nAPICallResult = ERROR_SUCCESS; } nResult = StopTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), bLogExpected, bUseTraceHandle, pstructTCOData, &nAPICallResult ); tsDetailFile.erase(); FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nResult; } int ActionEnableTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected ) { int nResult = ERROR_SUCCESS; LPTSTR lptstrTCOTestError = NULL; TCOData *pstructTCOData = NULL; TCOFunctionalData *pstructTCOFunctionalData = NULL; int nAPICallResult = 0; t_string tsDetailFile; t_string tsError; nResult = GetAllTCOData ( lptstrDataFile , &pstructTCOData, &pstructTCOFunctionalData, &lptstrTCOTestError ); if (nResult != ERROR_SUCCESS) { t_cout << _T("Could not get TCO Data: ") << lptstrTCOTestError << _T("\n"); FreeTCOData(pstructTCOData); pstructTCOData = NULL; FreeTCOFunctionalData(pstructTCOFunctionalData); pstructTCOFunctionalData = NULL; free(lptstrTCOTestError); lptstrTCOTestError = NULL; return nResult; } tsDetailFile = lptstrDetailPath; tsDetailFile += _T("\\"); tsDetailFile += GetTestName(lptstrDataFile); nResult = StartTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), false, pstructTCOData, &nAPICallResult ); // We have a problem here if nResult != ERROR_SUCCESS and nAPICallResult == ERROR_SUCCESS // we need to call EnableTrace so that the provider can be stopped via a StopTrace // call. if (nResult != ERROR_SUCCESS && nAPICallResult == ERROR_SUCCESS) { Sleep(2000); // Do not really care what result is! int nResult2 = EnableTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), false, pstructTCOData, &nAPICallResult ); Sleep(5000); // Restore this. nAPICallResult = ERROR_SUCCESS; } if (nResult == ERROR_SUCCESS) { Sleep(2000); nResult = EnableTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), bLogExpected, pstructTCOData, &nAPICallResult ); Sleep(5000); } tsDetailFile.erase(); FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nResult; } int ActionQueryTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected, bool bUseTraceHandle ) { int nResult = ERROR_SUCCESS; LPTSTR lptstrTCOTestError = NULL; TCOData *pstructTCOData = NULL; TCOFunctionalData *pstructTCOFunctionalData = NULL; int nAPICallResult = 0; t_string tsDetailFile; nResult = GetAllTCOData ( lptstrDataFile , &pstructTCOData, &pstructTCOFunctionalData, &lptstrTCOTestError ); if (nResult != ERROR_SUCCESS) { t_cout << _T("Could not get TCO Data: ") << lptstrTCOTestError << _T("\n"); FreeTCOData(pstructTCOData); pstructTCOData = NULL; FreeTCOFunctionalData(pstructTCOFunctionalData); pstructTCOFunctionalData = NULL; free(lptstrTCOTestError); lptstrTCOTestError = NULL; return nResult; } tsDetailFile = lptstrDetailPath; tsDetailFile += _T("\\"); tsDetailFile += GetTestName(lptstrDataFile); // If bUseTraceHandle is true we will start the logger. if (bUseTraceHandle) { nResult = StartTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), false, pstructTCOData, &nAPICallResult ); t_string tsError; if (nAPICallResult != ERROR_SUCCESS) { FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nAPICallResult; } Sleep(2000); int nResult2 = EnableTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), false, pstructTCOData, &nAPICallResult ); if (nAPICallResult != ERROR_SUCCESS) { FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nAPICallResult; } Sleep(5000); } nResult = QueryTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), bLogExpected, bUseTraceHandle, pstructTCOData, &nAPICallResult ); tsDetailFile.erase(); FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nResult; } int ActionUpdateTrace ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, LPTSTR lptstrUpdateDataFile, bool bLogExpected, bool bUseTraceHandle ) { int nResult = ERROR_SUCCESS; LPTSTR lptstrTCOTestError = NULL; TCOData *pstructTCOData = NULL; TCOData *pstructUpdateData = NULL; // Remember to free! TCOFunctionalData *pstructTCOFunctionalData = NULL; int nAPICallResult = 0; t_string tsDetailFile; if (bUseTraceHandle && !lptstrUpdateDataFile) { t_cout << _T("Error in ActionUpdateTrace: If -usetracehandle 1 is true you must provide an -updatedata argument.\n"); return -1; } if (bUseTraceHandle && lptstrUpdateDataFile) { nResult = GetAllTCOData ( lptstrUpdateDataFile , &pstructUpdateData, NULL, &lptstrTCOTestError, false ); } nResult = GetAllTCOData ( lptstrDataFile , &pstructTCOData, &pstructTCOFunctionalData, &lptstrTCOTestError ); if (nResult != ERROR_SUCCESS) { t_cout << _T("Could not get TCO Data: ") << lptstrTCOTestError << _T("\n"); FreeTCOData(pstructTCOData); pstructTCOData = NULL; FreeTCOFunctionalData(pstructTCOFunctionalData); pstructTCOFunctionalData = NULL; free(lptstrTCOTestError); lptstrTCOTestError = NULL; return nResult; } tsDetailFile = lptstrDetailPath; tsDetailFile += _T("\\"); tsDetailFile += GetTestName(lptstrDataFile); // If bUseTraceHandle is true we will start the logger. if (bUseTraceHandle) { nResult = StartTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), false, pstructTCOData, &nAPICallResult ); t_string tsError; if (nAPICallResult != ERROR_SUCCESS) { FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nAPICallResult; } Sleep(2000); int nResult2 = EnableTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), false, pstructTCOData, &nAPICallResult ); if (nAPICallResult != ERROR_SUCCESS) { FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); return nAPICallResult; } Sleep(5000); } if (bUseTraceHandle) { pstructUpdateData->m_pTraceHandle = (TRACEHANDLE *) malloc (sizeof(TRACEHANDLE)); *pstructUpdateData->m_pTraceHandle = *pstructTCOData->m_pTraceHandle; } nResult = UpdateTraceAPI ( lptstrAction, lptstrDataFile, tsDetailFile.c_str(), bLogExpected, bUseTraceHandle, bUseTraceHandle ? pstructUpdateData : pstructTCOData, &nAPICallResult ); tsDetailFile.erase(); FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); FreeTCOData(pstructUpdateData); return nResult; } int ActionQueryAllTraces ( LPTSTR lptstrAction, LPTSTR lptstrDetailPath ) { int nAPICallResult = ERROR_SUCCESS; int nResult = QueryAllTracesAPI ( lptstrAction, &nAPICallResult ); t_string tsError; if (nResult != ERROR_SUCCESS) { tsError = ULONGVarToTString(nResult, true); LPTSTR lptstrError = DecodeStatus(nResult); t_cout << _T("ActionQueryAllTraces Failure: ") << tsError; if (lptstrError) { t_cout << _T(" - ") << lptstrError << _T("\n"); } else { t_cout << _T(".\n"); } free (lptstrError); lptstrError = NULL; } return nResult; } int ActionStartProvider ( LPTSTR lptstrAction, LPTSTR lptstrProviderExe ) { t_string tsExeAndCmdLine; tsExeAndCmdLine = lptstrProviderExe; int nEndExe = tsExeAndCmdLine.find(_T(".exe")); nEndExe += 4; t_string tsExe; tsExe = tsExeAndCmdLine.substr(0,nEndExe); t_string tsCmdLine; if (nEndExe + 1 < tsExeAndCmdLine.length()) { tsCmdLine = tsExeAndCmdLine.substr(nEndExe + 1,t_string::npos); } PROCESS_INFORMATION pinfoProvider; RtlZeroMemory(&pinfoProvider, sizeof(PROCESS_INFORMATION)); STARTUPINFO sinfoProvider; RtlZeroMemory(&sinfoProvider, sizeof(STARTUPINFO)); sinfoProvider.cb = sizeof(sinfoProvider); sinfoProvider.lpReserved = NULL; sinfoProvider.lpDesktop = NULL; sinfoProvider.lpTitle = NULL; sinfoProvider.dwFlags = 0; sinfoProvider.cbReserved2 = 0; sinfoProvider.lpReserved2 = NULL; sinfoProvider.hStdInput = NULL; sinfoProvider.hStdOutput = NULL; sinfoProvider.hStdError = NULL; BOOL bReturn = CreateProcess( tsExe.c_str(), (TCHAR *) tsCmdLine.c_str(), NULL, NULL, NULL, DETACHED_PROCESS, NULL, NULL, &sinfoProvider, &pinfoProvider); if (!bReturn) { DWORD dwError = GetLastError(); t_cout << _T("\nCreateProcess failed for provider ") << tsExe << _T("\n"); t_cout << _T("with command line ") << tsCmdLine << _T(".\n"); LPTSTR lpstrReturnedError = DecodeStatus(dwError); t_cout << _T("Error: ") << lpstrReturnedError << _T("\n"); free(lpstrReturnedError); return ERROR_COULD_NOT_CREATE_PROCESS; } t_cout << _T("\nCreateProcess succeeded for provider ") << tsExe << _T("\n"); t_cout << _T("with command line ") << tsCmdLine << _T(".\n"); // Do not need to hold on to this! CloseHandle(pinfoProvider.hProcess); CloseHandle(pinfoProvider.hThread); // Give the process 5 seconds to get going. Sleep(5000); return ERROR_SUCCESS; } int ActionScenario ( LPTSTR lptstrAction, LPTSTR lptstrDataFile, LPTSTR lptstrDetailPath, bool bLogExpected ) { int nResult = ERROR_SUCCESS; LPTSTR lptstrTCOTestError = NULL; TCOData *pstructTCOData = NULL; TCOFunctionalData *pstructTCOFunctionalData = NULL; nResult = GetAllTCOData ( lptstrDataFile , &pstructTCOData, &pstructTCOFunctionalData, &lptstrTCOTestError ); if (nResult != ERROR_SUCCESS) { t_cout << _T("Could not get TCO Data: ") << lptstrTCOTestError << _T("\n"); FreeTCOData(pstructTCOData); pstructTCOData = NULL; FreeTCOFunctionalData(pstructTCOFunctionalData); pstructTCOFunctionalData = NULL; free(lptstrTCOTestError); lptstrTCOTestError = NULL; return nResult; } nResult = RunActionScenarioWithProvider ( pstructTCOData, pstructTCOFunctionalData, lptstrAction, lptstrDataFile, lptstrDetailPath, lptstrTCOTestError ); FreeTCOData(pstructTCOData); FreeTCOFunctionalData(pstructTCOFunctionalData); t_string tsError; if (nResult != ERROR_SUCCESS) { tsError = ULONGVarToTString(nResult, true); LPTSTR lptstrError = DecodeStatus(nResult); t_cout << _T("ActionScenario Failure: ") << tsError; if (lptstrError) { t_cout << _T(" - ") << lptstrError << _T("\n"); } else { t_cout << _T(".\n"); } free (lptstrError); lptstrError = NULL; } return nResult; } int RunActionScenarioWithProvider ( TCOData *pstructTCOData, TCOFunctionalData *pstructTCOFunctionalData, LPTSTR &lptstrAction, LPTSTR &lptstrDataFile, LPTSTR &lptstrDetailPath, LPTSTR &lptstrTCOTestError ) { bool bLast = false; int nResult = ERROR_SUCCESS; int i; ProcessData **pstructProviderDataArray = NULL; StartTraceWithProviderData **pstructStartTraceData = NULL; HANDLE *phandleProviderThreads = NULL; // Here we want to build up array of provider ProcessData./ // Start a thread for each. // Wait for all of the provider threads to complete. if (pstructTCOFunctionalData->m_nProviders > 0) { pstructStartTraceData = (StartTraceWithProviderData **) malloc (sizeof (StartTraceWithProviderData *) * pstructTCOFunctionalData->m_nProviders); RtlZeroMemory (pstructStartTraceData, sizeof (StartTraceWithProviderData *) * pstructTCOFunctionalData->m_nProviders); for (i = 0; i < pstructTCOFunctionalData->m_nProviders; i++) { pstructStartTraceData[i] = (StartTraceWithProviderData *) malloc (sizeof(StartTraceWithProviderData)); RtlZeroMemory (pstructStartTraceData[i], sizeof (StartTraceWithProviderData)); } pstructProviderDataArray = (ProcessData **) malloc (sizeof (ProcessData *) * pstructTCOFunctionalData->m_nProviders); RtlZeroMemory (pstructProviderDataArray, sizeof (ProcessData *) * pstructTCOFunctionalData->m_nProviders); phandleProviderThreads = (HANDLE *) malloc (sizeof (HANDLE) * pstructTCOFunctionalData->m_nProviders); RtlZeroMemory (phandleProviderThreads, sizeof (HANDLE) * pstructTCOFunctionalData->m_nProviders); for (int n = 0; n < pstructTCOFunctionalData->m_nProviders; n++) { pstructProviderDataArray[n] = InitializeProcessData ( pstructTCOData, pstructTCOFunctionalData, lptstrDetailPath, n, // 0 index gets the first provider or consumer. true // bProvider, if false we get Consumer. ); if (!pstructProviderDataArray[n]->m_hEventContinue || !pstructProviderDataArray[n]->m_hEventProcessCompleted) { lptstrTCOTestError = NewTCHAR(_T("Provider Data Array: Could not create events.")); FreeProcessDataArray (pstructProviderDataArray,pstructTCOFunctionalData->m_nProviders); return -1; } } } ProcessData **pstructConsumerDataArray = NULL; int npstructStartTraceDataWithConsumers = -1; for (i = 0; i < pstructTCOFunctionalData->m_nProviders; i++) { if (i == pstructTCOFunctionalData->m_nProviders - 1) { bLast = true; } bool bStartConsumers = (!pstructTCOData->m_pProps) ? false : (pstructTCOData->m_pProps->LogFileMode == EVENT_TRACE_REAL_TIME_MODE && i == 0) ? true : (pstructTCOData->m_pProps->LogFileMode != EVENT_TRACE_REAL_TIME_MODE && bLast) ? true: false; pstructStartTraceData[i]->m_pstructTCOData = pstructTCOData; pstructStartTraceData[i]->m_pstructTCOFunctionalData = pstructTCOFunctionalData; pstructStartTraceData[i]->m_lptstrAction = lptstrAction; pstructStartTraceData[i]->m_lptstrDataFile = lptstrDataFile; pstructStartTraceData[i]->m_lptstrDetailPath = lptstrDetailPath; pstructStartTraceData[i]->m_pstructProcessData = pstructProviderDataArray[i]; pstructStartTraceData[i]->m_bStartConsumers = bStartConsumers; pstructStartTraceData[i]->m_pstructConsumerDataArray = pstructConsumerDataArray; if (bStartConsumers) { pstructStartTraceData[i]->m_handleConsmers = (HANDLE *) malloc (sizeof(HANDLE) * pstructTCOFunctionalData->m_nConsumers); RtlZeroMemory(pstructStartTraceData[i]->m_handleConsmers, sizeof(HANDLE) * pstructTCOFunctionalData->m_nConsumers); npstructStartTraceDataWithConsumers = i; } // Start the provider processes via a thread. The thread will become // the surogate for thr process. UINT uiThreadId = NULL; phandleProviderThreads[i] = (HANDLE) _beginthreadex (NULL, 0, RunActionScenarioWithProvider, (void *) pstructStartTraceData[i], 0 , &uiThreadId); HANDLE hTemp = phandleProviderThreads[i]; ThreadLogger(3,_T("RunActionScenarioWithProvider"), _T("Just created thread with handle"),true, (ULONG)hTemp); if (phandleProviderThreads[i] == 0) { int nError = errno; lptstrTCOTestError = NewTCHAR(_T("Could not start RunActionScenarioWithProvider thread.")); nResult = nError; break; } } // Big logic here. This is where we wait for all of the // conusmer processes to complete if we have consumers and // all of the provider threads. The provider threads wait for the // provider processes to complete so we just wait on the threads. // One of the provider threads starts the consumer processes but // does not wait on them. So we wait on them here. Again, we // wait on the consumer threads. // After the threads complete we will call StopTrace. // Create an array to hold the handles HANDLE *phandleAllThreads = (HANDLE *) malloc (sizeof (HANDLE) * (pstructTCOFunctionalData->m_nProviders + pstructTCOFunctionalData->m_nConsumers)); RtlZeroMemory (phandleAllThreads, sizeof (HANDLE) * (pstructTCOFunctionalData->m_nProviders + pstructTCOFunctionalData->m_nConsumers)); int nHandles = 0; // Copy handles into it. for (i = 0; i < pstructTCOFunctionalData->m_nProviders; i++) { if (phandleProviderThreads[i]) { phandleAllThreads[nHandles++] = phandleProviderThreads[i]; } } for (i = 0; i < pstructTCOFunctionalData->m_nConsumers; i++) { if (pstructStartTraceData[npstructStartTraceDataWithConsumers]->m_handleConsmers[i]) { phandleAllThreads[nHandles++] = pstructStartTraceData[npstructStartTraceDataWithConsumers]->m_handleConsmers[i]; } } Sleep (5000); // Wait for the provider and consumer threads to complete. DWORD dwWait = WaitForMultipleObjects ( nHandles, phandleAllThreads, TRUE, 10000 ); free(phandleAllThreads); // Just free storage the handles get closed elsewhere. int nAPICallResult = 0; if (pstructStartTraceData[0]->m_pstructTCOData->m_pProps->LoggerName && pstructStartTraceData[0]->m_pstructTCOData->m_pProps) { nResult = StopTraceAPI ( lptstrAction, NULL, // Only use name. NULL, // If valid we will log to it, can be NULL. false, true, pstructStartTraceData[0]->m_pstructTCOData, &nAPICallResult ); if (nAPICallResult != ERROR_SUCCESS) { LPTSTR lptstrError = DecodeStatus(nAPICallResult); t_string tsError; tsError = _T("StopTraceAPI failed with error: "); tsError += lptstrError; lptstrTCOTestError = NewTCHAR(tsError.c_str()); free (lptstrError); lptstrError = NULL; nResult = nAPICallResult; } } // Need to CloseHandle(); before we free these guys! for (i = 0; i < pstructTCOFunctionalData->m_nProviders; i++) { if (phandleProviderThreads[i]) { if (phandleProviderThreads[i]) { CloseHandle(phandleProviderThreads[i]); } } } free (phandleProviderThreads); FreeProcessDataArray (pstructProviderDataArray,pstructTCOFunctionalData->m_nProviders); FreeProcessDataArray (pstructConsumerDataArray,pstructTCOFunctionalData->m_nConsumers); FreeStartTraceWithProviderDataArray (pstructStartTraceData,pstructTCOFunctionalData->m_nProviders); return nResult; } // This gets started in its own thread and its caller waits for it to complete. unsigned int __stdcall RunActionScenarioWithProvider(void *pVoid) { StartTraceWithProviderData *pData = (StartTraceWithProviderData *) pVoid; t_string tsLogMsg; tsLogMsg = _T("RunActionScenarioWithProvider"); ThreadLogger(1,tsLogMsg.c_str(),_T(""),false,0); pData->m_pstructConsumerDataArray = NULL; // We do not exit this function until the process has failed to be // created or has completed. We can not free things in the ProcessData // structure until we are sure that the thread has exited one way or // another. UINT uiThreadId = NULL; HANDLE hThreadProvider = (HANDLE) _beginthreadex (NULL, 0, RunProcess, (void *) pData->m_pstructProcessData, 0 , &uiThreadId); if (hThreadProvider == 0) { int nError = errno; pData->m_lptstrTCOTestError = NewTCHAR(_T("Could not start RunProcesss thread.")); ThreadLogger(3,_T("RunActionScenarioWithProvider"), pData->m_lptstrTCOTestError,true, nError); _endthreadex(nError); return nError; } DWORD dwReturn = WaitForSingleObject (pData->m_pstructProcessData->m_hEventContinue, 6000); // Give the thread 1 second to get going. Sleep(3000); // If the thread is not active there was a problem getting it // started so we will bail. DWORD dwExitCode; GetExitCodeThread(hThreadProvider, &dwExitCode); if (dwExitCode != STILL_ACTIVE || pData->m_pstructProcessData->m_dwThreadReturn == ERROR_COULD_NOT_CREATE_PROCESS) { CloseHandle(hThreadProvider); if (pData->m_pstructProcessData->m_dwThreadReturn == ERROR_COULD_NOT_CREATE_PROCESS) { pData->m_lptstrTCOTestError = NewTCHAR(_T("Could not create process.")); } else { pData->m_lptstrTCOTestError = NewTCHAR(_T("Error in RunProcesss thread.")); } if(pData->m_pstructProcessData->m_hProcess) { CloseHandle(pData->m_pstructProcessData->m_hProcess); pData->m_pstructProcessData->m_hProcess = NULL; } ThreadLogger(2,_T("RunActionScenarioWithProvider"), pData->m_lptstrTCOTestError,false, 0); _endthreadex(-1); return -1; } t_string tsDetailFile; if (pData->m_lptstrDetailPath) { tsDetailFile = pData->m_lptstrDetailPath; tsDetailFile += _T("\\"); tsDetailFile += GetTestName(pData->m_lptstrDataFile); } // nAPICallResult is what the StartTrace call returned. // If the call does not succeed we have to clean up the // process. If the call does succeed we need to call // EnableTrace to get the provider going. int nAPICallResult = ERROR_SUCCESS; int nResult = StartTraceAPI ( pData->m_lptstrAction, pData->m_lptstrDataFile, pData->m_lptstrDetailPath ? tsDetailFile.c_str() : NULL, false, pData->m_pstructTCOData, &nAPICallResult ); // Big assumption here! // If nAPICallResult == 0x000000a1 we assume that multiple StartTraces and that // the first one succeeded! if (nAPICallResult == ERROR_BAD_PATHNAME) { ThreadLogger(3,_T("RunActionScenarioWithProvider"), _T("StartTraceAPI function returned ERROR_BAD_PATHNAME. Proceeding."),false, 0); nAPICallResult = ERROR_SUCCESS; nResult = ERROR_SUCCESS; } else { ThreadLogger(3,_T("RunActionScenarioWithProvider"), _T("StartTraceAPI function returned "),true, nResult); ThreadLogger(3,_T("RunActionScenarioWithProvider"), _T("StartTrace API call returned "),true, nAPICallResult); } if (nAPICallResult != ERROR_SUCCESS) { // Here we must cleanup process because // provider is running and we must stop it! BOOL bResult = TerminateProcess(pData->m_pstructProcessData->m_hProcess,0); if (!bResult) { int nError = GetLastError(); ThreadLogger(3,_T("RunActionScenarioWithProvider"), _T("Could not terminate process "),true, nError); } // Do not want to free the data structures until process // terminates. Use thread as surrogate for process. GetExitCodeThread(hThreadProvider, &dwExitCode); while (dwExitCode == STILL_ACTIVE) { Sleep(500); GetExitCodeThread(hThreadProvider, &dwExitCode); } } // If we were able to call StartTrace successfully we must call // EnableTrace to get the provider going so it can complete. // If we do not successfully call EnableTrace we need to // clean up the thread and the process. if (nAPICallResult == ERROR_SUCCESS) { // If we cannot start the provider using the GUID in // Wnode.Guid we give up. Also, we do not care // if EnableTrace fails for the other GUIDs. ULONG ulStatus = EnableTraceAPI ( pData->m_lptstrAction, NULL, NULL, false, -1, pData->m_pstructTCOData, &nAPICallResult ); // Exit here after we clean up! if (nAPICallResult != ERROR_SUCCESS) { pData->m_lptstrTCOTestError = NewTCHAR(_T("Could not EnableTrace to start provider.")); // Here we must cleanup thread and process because // EnableTrace failed. TerminateProcess(pData->m_pstructProcessData->m_hProcess,0); // Do not want to free the data structures until process // terminates. Use thread as surrogate for process. GetExitCodeThread(hThreadProvider, &dwExitCode); while (dwExitCode == STILL_ACTIVE) { Sleep(500); } CloseHandle(hThreadProvider); if(pData->m_pstructProcessData->m_hProcess) { CloseHandle(pData->m_pstructProcessData->m_hProcess); pData->m_pstructProcessData->m_hProcess = NULL; } ThreadLogger(2,_T("RunActionScenarioWithProvider"), pData->m_lptstrTCOTestError,true,ulStatus); _endthreadex(nAPICallResult); return nAPICallResult; } if (pData->m_bStartConsumers) { if (pData->m_pstructTCOFunctionalData->m_nConsumers > 0) { pData->m_pstructConsumerDataArray = (ProcessData **) malloc (sizeof (ProcessData *) * pData->m_pstructTCOFunctionalData->m_nConsumers); RtlZeroMemory (pData->m_pstructConsumerDataArray, sizeof (ProcessData *) * pData->m_pstructTCOFunctionalData->m_nConsumers); int n; for (n = 0; n < pData->m_pstructTCOFunctionalData->m_nConsumers; n++) { pData->m_pstructConsumerDataArray[n] = InitializeProcessData ( pData->m_pstructTCOData, pData->m_pstructTCOFunctionalData, pData->m_lptstrDetailPath, n, // 0 index gets the first provider or consumer. false // bProvider, if false we get Consumer. ); if (!pData->m_pstructConsumerDataArray[n]->m_hEventContinue || !pData->m_pstructConsumerDataArray[n]->m_hEventProcessCompleted) { pData->m_lptstrTCOTestError = NewTCHAR(_T("Could not create events.")); CloseHandle(hThreadProvider); if(pData->m_pstructProcessData->m_hProcess) { CloseHandle(pData->m_pstructProcessData->m_hProcess); pData->m_pstructProcessData->m_hProcess = NULL; } ThreadLogger(2,_T("RunActionScenarioWithProvider"), pData->m_lptstrTCOTestError,false,0); _endthreadex(-1); return -1; } } for (n = 0; n < pData->m_pstructTCOFunctionalData->m_nConsumers; n++) { UINT uiThreadId = NULL; pData->m_handleConsmers[n] = (HANDLE) _beginthreadex (NULL, 0, RunProcess, (void *) pData->m_pstructConsumerDataArray[n], 0 , &uiThreadId); // We use the thread as the surrogate for the process because // we do not exit the thread until the process ends or is // terminated. if (pData->m_handleConsmers[n] == 0) { int nError = errno; pData->m_lptstrTCOTestError = NewTCHAR(_T("Could not start RunProcesss thread for consumer.")); CloseHandle(hThreadProvider); if(pData->m_pstructProcessData->m_hProcess) { CloseHandle(pData->m_pstructProcessData->m_hProcess); pData->m_pstructProcessData->m_hProcess = NULL; } ThreadLogger(2,_T("RunActionScenarioWithProvider"), pData->m_lptstrTCOTestError,true,errno); _endthreadex(errno); return nError; } Sleep(3000); // We do not need the handle to the process. if (pData->m_pstructConsumerDataArray[n]->m_hProcess) { CloseHandle(pData->m_pstructConsumerDataArray[n]->m_hProcess); pData->m_pstructConsumerDataArray[n]->m_hProcess = 0; } } } } // Enable the other GUIDS for provider. We do not check // the return code. for (int i = 0; i < pData->m_pstructTCOData->m_nGuids; i++) { EnableTraceAPI ( pData->m_lptstrAction, NULL, NULL, false, i, pData->m_pstructTCOData, &nAPICallResult ); Sleep(3000); } } // Do not need this. CloseHandle(hThreadProvider); if (nAPICallResult == ERROR_SUCCESS) { ThreadLogger(3,_T("RunActionScenarioWithProvider"), _T("About to wait for process to complete "),false, 0); dwReturn = WaitForSingleObject (pData->m_pstructProcessData->m_hEventProcessCompleted, 6000); ThreadLogger(3,_T("RunActionScenarioWithProvider"), _T("After wait for process to complete "),false, 0); } if (nResult != ERROR_SUCCESS) { t_string tsError; tsError = _T("Failure in RunActionScenarioWithProvider: StartTraceAPI failed."); pData->m_lptstrTCOTestError = NewTCHAR(tsError.c_str()); if (nAPICallResult != ERROR_SUCCESS) { if(pData->m_pstructProcessData->m_hProcess) { CloseHandle(pData->m_pstructProcessData->m_hProcess); pData->m_pstructProcessData->m_hProcess = NULL; } ThreadLogger(2,_T("RunActionScenarioWithProvider"), pData->m_lptstrTCOTestError,true,nResult); _endthreadex(nResult); return nResult; } } if(pData->m_pstructProcessData->m_hProcess) { CloseHandle(pData->m_pstructProcessData->m_hProcess); pData->m_pstructProcessData->m_hProcess = NULL; } ThreadLogger(2,_T("RunActionScenarioWithProvider"), _T("Normal exit"),true,nResult); _endthreadex(nResult); return nResult; } // This can deal with command line arguments in double quotes and // you must double quote command line arguments which contain spaces. t_string FindValue(t_string tsCommandLine, int nPos) { int nLen = tsCommandLine.length(); TCHAR tc = tsCommandLine[nPos]; bool bQuote = false; while ((nPos < nLen) && tc == _T(' ') || tc == _T('\t') || tc == _T('"')) { if (tc == _T('"')) { // Quotes allow embedded white spaces. bQuote = true; } ++nPos; tc = tsCommandLine[nPos]; } if (nPos == nLen) { return _T(""); // Empty string means failure. } int nEnd = nPos; tc = tsCommandLine[nEnd]; while ((nEnd < nLen) && ( (!bQuote && (tc != _T(' ') && tc != _T('\t'))) || (bQuote && tc != _T('"')) ) ) { ++nEnd; tc = tsCommandLine[nEnd]; } t_string tsReturn; tsReturn = tsCommandLine.substr(nPos,nEnd - nPos); return tsReturn; } int GetArgs ( t_string tsCommandLine, LPTSTR &lptstrAction, LPTSTR &lptstrDataFile, LPTSTR &lptstrDetailPath, LPTSTR &lptstrUpdateDataFile, LPTSTR &lptstrProviderExe, bool &bLogExpected, bool &bUseTraceHandle ) { int nFind; nFind = tsCommandLine.find(_T("-action")); t_string tsValue; if (nFind != t_string::npos) { nFind += 7; tsValue= FindValue(tsCommandLine,nFind); if (tsValue.empty()) { return -1; } else { lptstrAction = NewTCHAR(tsValue.c_str()); } tsValue.erase(); } nFind = tsCommandLine.find(_T("-file")); if (nFind != t_string::npos) { nFind += 5; tsValue= FindValue(tsCommandLine,nFind); if (tsValue.empty()) { return -1; } else { lptstrDataFile = NewTCHAR(tsValue.c_str()); } tsValue.erase(); } nFind = tsCommandLine.find(_T("-detail")); if (nFind == t_string::npos) { nFind += 7; tsValue= FindValue(tsCommandLine,nFind); if (tsValue.empty()) { return -1; } } else { nFind += 7; tsValue= FindValue(tsCommandLine,nFind); if (tsValue.empty()) { return -1; } else { lptstrDetailPath = NewTCHAR(tsValue.c_str()); } tsValue.erase(); } nFind = tsCommandLine.find(_T("-logexpected")); if (nFind != t_string::npos) { nFind += 12; tsValue= FindValue(tsCommandLine,nFind); if (tsValue.empty()) { return -1; } else { int nComp = tsValue.compare(_T("0")); if (nComp == 0) { bLogExpected = false; } else { bLogExpected = true; } } tsValue.erase(); } nFind = tsCommandLine.find(_T("-usetracehandle")); if (nFind != t_string::npos) { nFind += 15; tsValue= FindValue(tsCommandLine,nFind); if (tsValue.empty()) { return -1; } else { int nComp = tsValue.compare(_T("0")); if (nComp == 0) { bUseTraceHandle = false; } else { bUseTraceHandle = true; } } tsValue.erase(); } nFind = tsCommandLine.find(_T("-providerexe")); if (nFind != t_string::npos) { nFind += 12; tsValue= FindValue(tsCommandLine,nFind); if (tsValue.empty()) { return -1; } else { lptstrProviderExe = NewTCHAR(tsValue.c_str()); } tsValue.erase(); } nFind = tsCommandLine.find(_T("-updatedata")); if (nFind != t_string::npos) { nFind += 11; tsValue= FindValue(tsCommandLine,nFind); if (tsValue.empty()) { return -1; } else { lptstrUpdateDataFile = NewTCHAR(tsValue.c_str()); } tsValue.erase(); } return 0; } int FreeArgs ( LPTSTR &lptstrAction, LPTSTR &lptstrDataFile, LPTSTR &lptstrDetailPath, LPTSTR &lptstrUpdateDataFile, LPTSTR &lptstrProviderExe ) { free (lptstrAction); free (lptstrDataFile); free (lptstrDetailPath); free (lptstrUpdateDataFile); free (lptstrProviderExe); lptstrAction = NULL; lptstrDataFile = NULL; lptstrDetailPath = NULL; lptstrUpdateDataFile = NULL; lptstrProviderExe = NULL; return 0; } unsigned int __stdcall RunProcess(void * pVoid) { ProcessData *pProcessData = (ProcessData *) pVoid; pProcessData->m_dwProcessReturn = 0; pProcessData->m_dwThreadReturn = 0; pProcessData->m_nSystemError = 0; PROCESS_INFORMATION pinfoProvider; RtlZeroMemory(&pinfoProvider, sizeof(PROCESS_INFORMATION)); STARTUPINFO sinfoProvider; RtlZeroMemory(&sinfoProvider, sizeof(STARTUPINFO)); sinfoProvider.cb = sizeof(sinfoProvider); sinfoProvider.lpReserved = NULL; sinfoProvider.lpDesktop = NULL; sinfoProvider.lpTitle = NULL; sinfoProvider.dwFlags = 0; sinfoProvider.cbReserved2 = 0; sinfoProvider.lpReserved2 = NULL; sinfoProvider.hStdInput = NULL; sinfoProvider.hStdOutput = NULL; sinfoProvider.hStdError = NULL; BOOL bReturn = CreateProcess( pProcessData->m_lptstrExePath, pProcessData->m_lptstrCmdLine, NULL, NULL, NULL, DETACHED_PROCESS, NULL, NULL, &sinfoProvider, &pinfoProvider); if (!bReturn) { pProcessData->m_nSystemError = GetLastError(); pProcessData->m_dwThreadReturn = ERROR_COULD_NOT_CREATE_PROCESS; SetEvent(pProcessData->m_hEventContinue); _endthreadex(ERROR_COULD_NOT_CREATE_PROCESS); return ERROR_COULD_NOT_CREATE_PROCESS; } pProcessData->m_hProcess = pinfoProvider.hProcess; // Do not need to hold on to this! CloseHandle(pinfoProvider.hThread); // Give the process 5 seconds to get going. Sleep(5000); SetEvent(pProcessData->m_hEventContinue); pProcessData->m_dwProcessReturn = WaitForSingleObject(pinfoProvider.hProcess,6000); if (pProcessData->m_dwProcessReturn != WAIT_OBJECT_0) { pProcessData->m_nSystemError = GetLastError(); pProcessData->m_dwThreadReturn = ERROR_WAIT_FAILED; SetEvent(pProcessData->m_hEventProcessCompleted); _endthreadex(ERROR_WAIT_FAILED); return (ERROR_WAIT_FAILED); } bReturn = GetExitCodeProcess (pinfoProvider.hProcess, &pProcessData->m_dwProcessReturn); if (!bReturn) { pProcessData->m_nSystemError = GetLastError(); pProcessData->m_dwThreadReturn = ERROR_COULD_NOT_GET_PROCESS_RETURN; SetEvent(pProcessData->m_hEventProcessCompleted); _endthreadex(ERROR_COULD_NOT_GET_PROCESS_RETURN); return (ERROR_COULD_NOT_GET_PROCESS_RETURN); } bReturn = SetEvent(pProcessData->m_hEventProcessCompleted); if (!bReturn) { int n = GetLastError(); } _endthreadex(0); return (0); } t_string GetTestName(LPTSTR lptstrDataFile) { t_string tsTemp; tsTemp = lptstrDataFile; t_string tsPath; int nBeg = tsTemp.find_last_of(_T('\\')); ++nBeg; int nEnd = tsTemp.find_last_of(_T('.')); if (nEnd == t_string::npos) { nEnd = tsTemp.length(); } int nNum = nEnd - nBeg; tsTemp = tsTemp.substr(nBeg, nNum); tsTemp += _T("Detail.txt"); return tsTemp; } ProcessData *InitializeProcessData ( TCOData *pstructTCOData, TCOFunctionalData *pstructTCOFunctionalData, LPTSTR lptstrDetailPath, int nProcessIndex, bool bProvider ) { ProcessData *pstructProcessData = (ProcessData *) malloc(sizeof(ProcessData)); RtlZeroMemory(pstructProcessData, sizeof(ProcessData)); InitializeExeAndCmdLine ( pstructProcessData, pstructTCOData, pstructTCOFunctionalData, lptstrDetailPath, nProcessIndex, bProvider ); pstructProcessData->m_lptstrTCOId = NewTCHAR(pstructTCOData->m_lptstrShortDesc); pstructProcessData->m_lptstrLogFile = NewTCHAR(lptstrDetailPath); // First Guid is in the properties. int nGuids; int nDelta; if (pstructTCOData->m_pProps != NULL) { nGuids= pstructTCOData->m_nGuids + 1; pstructProcessData->m_lpguidArray = (GUID *) malloc (sizeof (GUID) * nGuids); pstructProcessData->m_lpguidArray[0] = pstructTCOData->m_pProps->Wnode.Guid; nDelta = 1; } else { nGuids= pstructTCOData->m_nGuids; if (nGuids > 0) { pstructProcessData->m_lpguidArray = (GUID *) malloc (sizeof (GUID) * nGuids); } else { pstructProcessData->m_lpguidArray = NULL; } nDelta = 0; } for (int i = 0; i < pstructTCOData->m_nGuids; i++) { pstructProcessData->m_lpguidArray[i + nDelta] = pstructTCOData->m_lpguidArray[i]; } pstructProcessData->m_hEventContinue = CreateEvent(NULL,FALSE,FALSE,NULL);; pstructProcessData->m_hEventProcessCompleted = CreateEvent(NULL,FALSE,FALSE,NULL);; pstructProcessData->m_hProcess = NULL; pstructProcessData->m_dwProcessReturn = 0; pstructProcessData->m_dwThreadReturn = 0; pstructProcessData->m_nSystemError = 0; return pstructProcessData; } void InitializeExeAndCmdLine ( ProcessData *&pstructProcessData, TCOData *pstructTCOData, TCOFunctionalData *pstructTCOFunctionalData, LPTSTR lptstrDetailPath, int nProcessIndex, bool bProvider ) { t_string tsProcess; if (bProvider) { tsProcess = pstructTCOFunctionalData->m_lptstrProviderArray[nProcessIndex]; } else { tsProcess = pstructTCOFunctionalData->m_lptstrConsumerArray[nProcessIndex]; } t_string tsExe; t_string tsCmdLine; int nEndExe = tsProcess.find(_T(".exe")); nEndExe += 4; tsExe = tsProcess.substr(0,nEndExe); if (nEndExe + 1 < tsExe.length()) { tsCmdLine = tsProcess.substr(nEndExe + 1,t_string::npos); } tsCmdLine += _T(" -TESTID "); tsCmdLine += pstructTCOData->m_lptstrShortDesc; if (lptstrDetailPath) { tsCmdLine += _T("-TESTLOGPATH "); tsCmdLine += lptstrDetailPath; } tsCmdLine += _T("-GUIDS "); LPTSTR lptstrGuid = NULL; if (pstructTCOData->m_pProps != 0 && pstructTCOData->m_pProps->Wnode.Guid.Data1 != 0 && pstructTCOData->m_pProps->Wnode.Guid.Data2 != 0 && pstructTCOData->m_pProps->Wnode.Guid.Data3 != 0) { lptstrGuid = LPTSTRFromGuid(pstructTCOData->m_pProps->Wnode.Guid); tsCmdLine += lptstrGuid; free (lptstrGuid); lptstrGuid = NULL; if (pstructTCOData->m_nGuids > 0) { tsCmdLine += _T(","); } } if (pstructTCOData->m_pProps != 0) { for (int i = 0; i < pstructTCOData->m_nGuids; i++) { lptstrGuid = LPTSTRFromGuid(pstructTCOData->m_lpguidArray[i]); tsCmdLine += lptstrGuid; free (lptstrGuid); lptstrGuid = NULL; if (pstructTCOData->m_nGuids > 1 && i < pstructTCOData->m_nGuids - 1) { tsCmdLine += _T(","); } } } t_string tsTemp; if (bProvider) { tsCmdLine += _T(" -EnableFlag "); tsTemp = ULONGVarToTString(pstructTCOData->m_ulEnableFlag ,true); tsCmdLine += tsTemp; tsCmdLine += _T(" -EnableLevel "); tsTemp = ULONGVarToTString(pstructTCOData->m_ulEnableLevel ,true); tsCmdLine += tsTemp; } else { if (pstructTCOData->m_pProps != 0) { tsCmdLine += _T(" -LogFile "); tsCmdLine += pstructTCOData->m_pProps->LogFileName; tsCmdLine += _T(" -Logger "); tsCmdLine += pstructTCOData->m_pProps->LoggerName; } } pstructProcessData->m_lptstrExePath = NewTCHAR(tsExe.c_str()); pstructProcessData->m_lptstrCmdLine = NewTCHAR(tsCmdLine.c_str()); } void FreeProcessDataArray(ProcessData **pProcessData, int nProcessData) { if (pProcessData == NULL) { return; } for (int i = 0; i < nProcessData; i++) { if (pProcessData[i]) { FreeProcessData(pProcessData[i]); } } free (pProcessData); } void FreeProcessData(ProcessData *pProcessData) { free (pProcessData->m_lptstrExePath); free (pProcessData->m_lptstrCmdLine); free (pProcessData->m_lptstrTCOId); free (pProcessData->m_lptstrLogFile); free (pProcessData->m_lpguidArray); pProcessData->m_nGuids = 0; if (pProcessData->m_hEventContinue) { if (pProcessData->m_hEventContinue) { CloseHandle(pProcessData->m_hEventContinue); } } if (pProcessData->m_hEventProcessCompleted) { if (pProcessData->m_hEventProcessCompleted) { CloseHandle(pProcessData->m_hEventProcessCompleted); } } if (pProcessData->m_hProcess) { if (pProcessData->m_hProcess) { CloseHandle(pProcessData->m_hProcess); } } pProcessData->m_lptstrExePath = NULL; pProcessData->m_lptstrCmdLine = NULL; pProcessData->m_lptstrTCOId = NULL; pProcessData->m_lptstrLogFile = NULL; pProcessData->m_lpguidArray = NULL; pProcessData->m_hEventContinue = NULL; pProcessData->m_hEventProcessCompleted = NULL; pProcessData->m_hProcess = NULL; free (pProcessData); } void FreeStartTraceWithProviderData(StartTraceWithProviderData *p) { if (!p) { return; } free (p->m_lptstrTCOTestError); p->m_lptstrTCOTestError = NULL; int nConsumers = p->m_pstructTCOFunctionalData->m_nConsumers; if (p->m_handleConsmers) { for (int i = 0; i < nConsumers; i++) { CloseHandle(p->m_handleConsmers[i]); } free(p->m_handleConsmers); } free(p); // All other data is shared and freed elsewhere! } void FreeStartTraceWithProviderDataArray(StartTraceWithProviderData **p, int nP) { if (!p) { return; } for (int i = 0; i < nP; i++) { if (p[i]) { FreeStartTraceWithProviderData(p[i]); } } free(p); } // nState 1 = entering, 2 - leaving, 3 = none of the above. void ThreadLogger (int nState, LPCTSTR lptstrFunction, LPCTSTR lptstrMsg, bool bUseULONGValue, ULONG ulValue) { CRITICAL_SECTION csMyCriticalSection; InitializeCriticalSection (&csMyCriticalSection); __try { EnterCriticalSection (&csMyCriticalSection); g_ThreadLogger.LogTCHAR(_T("\n")); g_ThreadLogger.LogTCHAR(_T("Thread ID: ")); g_ThreadLogger.LogULONG((ULONG) GetCurrentThreadId()); g_ThreadLogger.LogTCHAR(_T(".\n")); if (nState == 1) { g_ThreadLogger.LogTCHAR(_T("Entering - ")); } else if (nState == 2) { g_ThreadLogger.LogTCHAR(_T("Leaving - ")); } g_ThreadLogger.LogTCHAR(lptstrFunction); if (_tcslen(lptstrMsg) > 0) { g_ThreadLogger.LogTCHAR(_T(":\n")); g_ThreadLogger.LogTCHAR(lptstrMsg); } if (bUseULONGValue) { g_ThreadLogger.LogTCHAR(_T(" - ")); g_ThreadLogger.LogULONG(ulValue); } g_ThreadLogger.LogTCHAR(_T(".\n")); } __finally { // Release ownership of the critical section LeaveCriticalSection (&csMyCriticalSection); } }