2499 lines
55 KiB
C++
2499 lines
55 KiB
C++
// 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);
|
|
|
|
}
|
|
|
|
}
|