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.
 
 
 
 
 
 

2498 lines
53 KiB

// 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 <iostream>
#include <strstream>
#include <fstream>
#include <string>
#include <sstream>
#include <map>
#include <list>
using namespace std;
#include <tchar.h>
#include <process.h>
#include <windows.h>
#ifdef NONNT5
typedef unsigned long ULONG_PTR;
#endif
#include <wmistr.h>
#include <guiddef.h>
#include <initguid.h>
#include <evntrace.h>
#include <WTYPES.H>
#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);
}
}