Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1459 lines
44 KiB

///////////////////////////////////////////////////////////////////////////
// File: WinHttpStressScheduler.cpp
//
// Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
//
// Purpose:
// ServerCommands.cpp: implementation of the ServerCommands class.
// This class is used to retrieve and act on command from the server.
//
// History:
// 02/08/01 DennisCh Created
//
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Includes
//////////////////////////////////////////////////////////////////////
//
// WIN32 headers
//
//
// Project headers
//
#include "ServerCommands.h"
#include "NetworkTools.h"
//////////////////////////////////////////////////////////////////////
// Globals and statics
//////////////////////////////////////////////////////////////////////
HANDLE g_hQueryServerForCommands; // Handle for the thread that queries the server for commands
CRITICAL_SECTION g_csServerCommandsVars; // For protecting CommandServer private member vars. Used in the QueryServerForCommands_ThreadProc.
extern ServerCommands g_objServerCommands; // Declared in WinHttpStressScheduler.cpp
////////////////////////////////////////////////////////////
// Function: QueryServerForCommands_ThreadProc(LPVOID)
//
// Purpose:
// This method sends a request to the command server for instructions
// and saves them in the public vars of ServerCommands.
//
////////////////////////////////////////////////////////////
DWORD
WINAPI
QueryServerForCommands_ThreadProc(
LPVOID lpParam // [IN] thread proc param
)
{
BOOL bResult = TRUE;
HINTERNET hRoot = NULL;
HINTERNET hSession = NULL;
HINTERNET hRequest = NULL;
URL_COMPONENTSW urlComponents;
// Allocate space for URL components
ZeroMemory(&urlComponents, sizeof(urlComponents));
urlComponents.dwSchemeLength = MAX_PATH;
urlComponents.lpszScheme = new TCHAR[MAX_PATH];
urlComponents.dwHostNameLength = MAX_PATH;
urlComponents.lpszHostName = new TCHAR[MAX_PATH];
urlComponents.dwUrlPathLength = MAX_PATH;
urlComponents.lpszUrlPath = new TCHAR[MAX_PATH];
urlComponents.dwExtraInfoLength = MAX_PATH;
urlComponents.lpszExtraInfo = new TCHAR[MAX_PATH];
urlComponents.dwUserNameLength = MAX_PATH;
urlComponents.lpszUserName = new TCHAR[MAX_PATH];
urlComponents.dwPasswordLength = MAX_PATH;
urlComponents.lpszPassword = new TCHAR[MAX_PATH];
urlComponents.nPort = 0;
urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
// crack the Command Server URL to be used later
if (!WinHttpCrackUrl(
g_objServerCommands.Get_CommandServerURL(),
_tcslen(g_objServerCommands.Get_CommandServerURL()),
ICU_ESCAPE,
&urlComponents)
)
{
bResult = FALSE;
goto Exit;
}
hRoot = WinHttpOpen(
STRESS_SCHEDULER_USER_AGENT,
WINHTTP_ACCESS_TYPE_NO_PROXY,
NULL,
NULL,
0);
if (!hRoot)
{
bResult = FALSE;
goto Exit;
}
hSession = WinHttpConnect(
hRoot,
urlComponents.lpszHostName,
// If the URL in urlComponents uses standard HTTP or HTTPS ports then use INTERNET_DEFAULT_PORT. Otherwise use the non-standard port gleaned from the URL.
((urlComponents.nPort == 80) || (urlComponents.nPort == 443)) ? INTERNET_DEFAULT_PORT : urlComponents.nPort,
0);
if (!hSession)
{
bResult = FALSE;
goto Exit;
}
// Build a full URL with path and querystring
TCHAR szFullPath[MAX_PATH*2];
ZeroMemory(szFullPath, sizeof(szFullPath));
_tcsncpy(szFullPath, urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
//szFullPath[urlComponents.dwUrlPathLength] = _T('\0');
_tcsncat(szFullPath, urlComponents.lpszExtraInfo, urlComponents.dwExtraInfoLength);
hRequest = WinHttpOpenRequest(
hSession,
_T("POST"),
szFullPath,
NULL,
NULL,
NULL,
// if the URL in urlComponents uses HTTPS then pass in WINHTTP_FLAG_SECURE to this param. Otherwise, 0.
(0 == _tcsnicmp(urlComponents.lpszScheme, _T("https"), 5)) ? WINHTTP_FLAG_SECURE : 0);
if (!hRequest)
{
bResult = FALSE;
goto Exit;
}
// Set reasonable timeouts just in case
if (!WinHttpSetTimeouts(hRequest, 5000, 5000, 5000, 5000))
{
bResult = FALSE;
goto Exit;
}
// Get the computer name and send it in a POST request
LPSTR szPost, szMachineName;
szPost = new CHAR[MAX_PATH];
szMachineName = new CHAR[MAX_PATH];
GetEnvironmentVariableA("COMPUTERNAME", szMachineName, MAX_PATH);
strcpy(szPost, FIELDNAME__USERINFO_MACHINENAME);
strcat(szPost, szMachineName);
bResult = WinHttpSendRequest(
hRequest,
_T("Content-Type: application/x-www-form-urlencoded"),
-1L,
szPost,
strlen(szPost),
strlen(szPost),
0);
delete [] szPost;
delete [] szMachineName;
szPost = NULL;
szMachineName = NULL;
if (!WinHttpReceiveResponse(hRequest, NULL))
{
bResult = FALSE;
goto Exit;
}
TCHAR szBuffer[MAX_URL];
DWORD dwBufferSize, dwIndex;
// get all command headers that we're interested in.
// make sure there are no pending operations on member vars (pServerCommands->Set_* functions)
EnterCriticalSection(&g_csServerCommandsVars);
// *********************************
// **** COMMANDHEADER__EXIT: Exit if header is present, else continue.
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__EXIT, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_ExitStress(TRUE);
else
g_objServerCommands.Set_ExitStress(FALSE);
// *********************************
// **** COMMANDHEADER__WINHTTP_DLL_URL: valid values: Valid URL
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__WINHTTP_DLL_URL, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_WinHttpDllURL(szBuffer, dwBufferSize);
else
bResult = FALSE;
// *********************************
// **** COMMANDHEADER__WINHTTP_PDB_URL: valid values: Valid URL
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__WINHTTP_PDB_URL, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_WinHttpPDBURL(szBuffer, dwBufferSize);
else
bResult = FALSE;
// *********************************
// **** COMMANDHEADER__WINHTTP_SYM_URL: valid values: Valid URL
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__WINHTTP_SYM_URL, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_WinHttpSYMURL(szBuffer, dwBufferSize);
else
bResult = FALSE;
// *********************************
// **** COMMANDHEADER__COMMANDSERVER_URL: valid values: Valid URL
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__COMMANDSERVER_URL, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_CommandServerURL(szBuffer, dwBufferSize);
else
bResult = FALSE;
// *********************************
// **** COMMANDHEADER__BEGIN_TIME_HOUR: valid values: Valid string from 0-23
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__BEGIN_TIME_HOUR, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_TimeStressBegins(szBuffer, NULL);
else
bResult = FALSE;
// *********************************
// **** COMMANDHEADER__BEGIN_TIME_MINUTE: valid values: Valid string from 0-59
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__BEGIN_TIME_MINUTE, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_TimeStressBegins(NULL, szBuffer);
else
bResult = FALSE;
// *********************************
// **** COMMANDHEADER__END_TIME_HOUR: valid values: Valid string from 0-23
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__END_TIME_HOUR, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_TimeStressEnds(szBuffer, NULL);
else
bResult = FALSE;
// *********************************
// **** COMMANDHEADER__END_TIME_MINUTE: valid values: Valid string from 0-59
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__END_TIME_MINUTE, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_TimeStressEnds(NULL, szBuffer);
else
bResult = FALSE;
// *********************************
// **** COMMANDHEADER__RUN_FOREVER: valid values: doesn't matter. As long as header is present it gets sent
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__RUN_FOREVER, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_RunForever(TRUE);
else
g_objServerCommands.Set_RunForever(FALSE);
// *********************************
// **** COMMANDHEADER__UPDATE_INTERVAL: valid values: Valid string in INTERNET_RFC1123 format
DWORD dwTimeOut;
dwTimeOut = 0;
dwIndex = 0;
dwBufferSize = sizeof(DWORD);
ZeroMemory(szBuffer, sizeof(szBuffer));
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_NUMBER, COMMANDHEADER__UPDATE_INTERVAL, &dwTimeOut, &dwBufferSize, &dwIndex))
g_objServerCommands.Set_CommandServerUpdateInterval(dwTimeOut);
else
bResult = FALSE;
// *********************************
// *********************************
// **** Query commands for building stress Instance objects
// ****
// **** COMMANDHEADER__STRESS_EXE_URL: valid values: Valid URL
DWORD dwStressExeID;
DWORD dwPageHeapCommandIndex,
dwUMDHCommandIndex,
dwStressPDBIndex,
dwStressSYMIndex,
dwStressMemDmpPathIndex,
dwStressExeIDIndex;
LPTSTR szPageheapCommand,
szUMDHCommand,
szStressPDB_URL,
szStressSYM_URL,
szStressMemDmpPath,
szStressExeID;
szPageheapCommand = new TCHAR[MAX_PATH];
szUMDHCommand = new TCHAR[MAX_PATH];
szStressPDB_URL = new TCHAR[MAX_STRESS_URL];
szStressSYM_URL = new TCHAR[MAX_STRESS_URL];
szStressMemDmpPath = new TCHAR[MAX_PATH];
szStressExeID = new TCHAR[MAX_PATH];
if (!g_objServerCommands.IsStressRunning())
{
// free all old StressExeURLs first - we're replacing it with new URLs anyway
g_objServerCommands.Clear_StressExeURLs();
dwIndex = 0;
dwStressExeIDIndex = 0;
dwPageHeapCommandIndex = 0;
dwUMDHCommandIndex = 0;
dwStressPDBIndex = 0;
dwStressSYMIndex = 0;
dwStressMemDmpPathIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
while (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_EXE_URL, szBuffer, &dwBufferSize, &dwIndex))
{
// *************************************
// *************************************
// ** COMMANDHEADER__MEMORY_DUMP_PATH: A valid path
ZeroMemory(szStressMemDmpPath, MAX_PATH);
dwBufferSize = MAX_PATH;
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__MEMORY_DUMP_PATH, szStressMemDmpPath, &dwBufferSize, &dwStressMemDmpPathIndex);
// *************************************
// *************************************
// ** Get COMMANDHEADER__STRESS_PDB_URL if there is one
// **
ZeroMemory(szStressPDB_URL, MAX_STRESS_URL);
dwBufferSize = MAX_STRESS_URL;
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_PDB_URL, szStressPDB_URL, &dwBufferSize, &dwStressPDBIndex);
// *************************************
// *************************************
// ** Get COMMANDHEADER__STRESS_SYM_URL if there is one
// **
ZeroMemory(szStressSYM_URL, MAX_STRESS_URL);
dwBufferSize = MAX_STRESS_URL;
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_SYM_URL, szStressSYM_URL, &dwBufferSize, &dwStressSYMIndex);
// *************************************
// *************************************
// ** Get COMMANDHEADER__STRESS_EXE_PAGEHEAP if there is one
// **
ZeroMemory(szPageheapCommand, MAX_PATH);
dwBufferSize = MAX_PATH;
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_EXE_PAGEHEAP, szPageheapCommand, &dwBufferSize, &dwPageHeapCommandIndex);
// *************************************
// *************************************
// ** Get COMMANDHEADER__STRESS_EXE_UMDH if there is one
// **
ZeroMemory(szUMDHCommand, MAX_PATH);
dwBufferSize = MAX_PATH;
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_EXE_UMDH, szUMDHCommand, &dwBufferSize, &dwUMDHCommandIndex);
// *************************************
// *************************************
// ** Get COMMANDHEADER__STRESS_EXE_INSTANCEID
// For each COMMANDHEADER__STRESS_EXE_URL, there must be an index for the stress instance from the StressADMIN DB table.
// This identifies the stressinstance run. The test case (stressinstance) WILL NOT be added and run without an ID number.
ZeroMemory(szStressExeID, MAX_PATH);
dwBufferSize = MAX_PATH;
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__STRESS_EXE_INSTANCEID, szStressExeID, &dwBufferSize, &dwStressExeIDIndex))
{
// convert header ID string to a DWORD
dwStressExeID = _ttol(szStressExeID);
// only add valid stressInstances with valid ID's
if (0 < dwStressExeID)
{
g_objServerCommands.Create_StressInstance(
dwStressExeID,
szPageheapCommand,
szUMDHCommand,
szStressPDB_URL,
szStressSYM_URL,
szStressMemDmpPath,
szBuffer);
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, MAX_URL);
}
}
}
}
delete [] szPageheapCommand;
delete [] szUMDHCommand;
delete [] szStressMemDmpPath;
delete [] szStressPDB_URL;
delete [] szStressSYM_URL;
delete [] szStressExeID;
// *********************************
// **** COMMANDHEADER__ABORT: Abort the stress instance running specified by this header.
dwIndex = 0;
dwBufferSize = MAX_URL;
ZeroMemory(szBuffer, sizeof(szBuffer));
while (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CUSTOM, COMMANDHEADER__ABORT, szBuffer, &dwBufferSize, &dwIndex))
g_objServerCommands.AbortStressInstance(_ttol(szBuffer));
LeaveCriticalSection(&g_csServerCommandsVars);
Exit:
if (hRequest)
WinHttpCloseHandle(hRequest);
if (hSession)
WinHttpCloseHandle(hSession);
if (hRoot)
WinHttpCloseHandle(hRoot);
delete [] urlComponents.lpszScheme;
delete [] urlComponents.lpszHostName;
delete [] urlComponents.lpszUrlPath;
delete [] urlComponents.lpszExtraInfo;
delete [] urlComponents.lpszPassword;
delete [] urlComponents.lpszUserName;
ExitThread(bResult);
}
// *******************************************************************
// *******************************************************************
// ****
// **** ServerCommands class member functions
// ****
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
ServerCommands::ServerCommands()
{
m_dwCommandServerUpdateInternval = STRESS_COMMAND_SERVER_UPDATE_INTERVAL;
m_bExit = FALSE;
m_dwStressInstanceIterator = NULL;
g_hQueryServerForCommands = NULL;
m_szCommandServerURL = new TCHAR[MAX_STRESS_URL];
m_szCommandServerResultsURL = new TCHAR[MAX_STRESS_URL];
m_szWinHttpDLL_DownloadURL = new TCHAR[MAX_STRESS_URL];
m_szWinHttpPDB_DownloadURL = new TCHAR[MAX_STRESS_URL];
m_szWinHttpSYM_DownloadURL = new TCHAR[MAX_STRESS_URL];
m_szWinHttpDLL_FileName = new TCHAR[MAX_PATH];
m_szStressSchedulerCurrentDirectory = new TCHAR[MAX_PATH];
m_szClientMachineName = new CHAR[MAX_PATH];
ZeroMemory(m_szCommandServerURL, MAX_STRESS_URL);
ZeroMemory(m_szCommandServerResultsURL, MAX_STRESS_URL);
ZeroMemory(m_szWinHttpDLL_DownloadURL, MAX_STRESS_URL);
ZeroMemory(m_szWinHttpPDB_DownloadURL, MAX_STRESS_URL);
ZeroMemory(m_szWinHttpSYM_DownloadURL, MAX_STRESS_URL);
ZeroMemory(m_szWinHttpDLL_FileName, MAX_PATH);
ZeroMemory(m_szStressSchedulerCurrentDirectory, MAX_PATH);
ZeroMemory(m_szClientMachineName, MAX_PATH);
// initilize start/end times to -1 so we know that
// there are not valid time and we'll skip the Begin/End stress time check
// until we get real values from the command server
m_iTimeStressBeginsHour = -1;
m_iTimeStressBeginsMinute = -1;
m_iTimeStressEndsHour = -1;
m_iTimeStressEndsMinute = -1;
m_bRunForever = 0;
// Set default URLs
wcsncpy(m_szCommandServerURL, STRESS_COMMAND_SERVER_URL, sizeof(STRESS_COMMAND_SERVER_URL));
wcsncpy(m_szCommandServerResultsURL, STRESS_COMMAND_SERVER_RESULTS_URL, sizeof(STRESS_COMMAND_SERVER_RESULTS_URL));
// Get the current working directory
GetCurrentDirectory(MAX_PATH, m_szStressSchedulerCurrentDirectory);
// Get the client's machine name
GetEnvironmentVariableA("COMPUTERNAME", m_szClientMachineName, MAX_PATH);
InitializeCriticalSection(&g_csServerCommandsVars);
// Tell the client that we are alive and also send system info
RegisterClient();
}
ServerCommands::~ServerCommands()
{
DWORD dwThreadExitCode = 0;
// LOGLOG: stressScheduler has exited
NetworkTools__SendLog(FIELDNAME__LOGTYPE_EXIT, "WinHttpStressScheduler has exited.", NULL, NULL);
// Shut down QueryServer thread
GetExitCodeThread(g_hQueryServerForCommands, &dwThreadExitCode);
if (STILL_ACTIVE == dwThreadExitCode)
WaitForSingleObject(g_hQueryServerForCommands, INFINITE);
// free allocated memory for URLs
Clear_StressExeURLs();
// Free our handles
CloseHandle(g_hQueryServerForCommands);
DeleteCriticalSection(&g_csServerCommandsVars);
delete [] m_szCommandServerURL;
delete [] m_szCommandServerResultsURL;
delete [] m_szWinHttpDLL_DownloadURL;
delete [] m_szWinHttpPDB_DownloadURL;
delete [] m_szWinHttpSYM_DownloadURL;
delete [] m_szWinHttpDLL_FileName;
delete [] m_szStressSchedulerCurrentDirectory;
delete [] m_szClientMachineName;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::GetCurrentWorkingDirectory()
//
// Purpose:
// Returns string containing the current working directory for
// this application.
//
////////////////////////////////////////////////////////////
LPTSTR
ServerCommands::Get_CurrentWorkingDirectory()
{
return m_szStressSchedulerCurrentDirectory;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Get_ClientMachineName()
//
// Purpose:
// Returns string containing the machine's NETBIOS name
//
////////////////////////////////////////////////////////////
LPSTR
ServerCommands::Get_ClientMachineName()
{
return m_szClientMachineName;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::QueryServerForCommands()
//
// Purpose:
// This method sends a request to the command server for instructions
// and saves them in our private vars.
//
////////////////////////////////////////////////////////////
ServerCommands::QueryServerForCommands()
{
BOOL bResult = TRUE;
DWORD dwThreadID = 0;
DWORD dwTimeOut = 0;
DWORD dwThreadExitCode = 0;
// See if thread is still active before spinning off a new one
GetExitCodeThread(g_hQueryServerForCommands, &dwThreadExitCode);
if (STILL_ACTIVE == dwThreadExitCode)
{
// wait for existing thread to finish
dwTimeOut = 0;
dwTimeOut = WaitForSingleObject(g_hQueryServerForCommands, 500);
if (WAIT_TIMEOUT == dwTimeOut)
bResult = FALSE;
}
else
{
// free handle for previous thread
CloseHandle(g_hQueryServerForCommands);
// spin off thread to query server
g_hQueryServerForCommands = NULL;
g_hQueryServerForCommands = CreateThread(NULL, 0, QueryServerForCommands_ThreadProc, (LPVOID) this, 0, &dwThreadID);
if (!g_hQueryServerForCommands)
bResult = FALSE;
}
return bResult;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Download_WinHttpDLL()
//
// Purpose:
// Downloads the test DLL and symbols.
//
////////////////////////////////////////////////////////////
BOOL ServerCommands::Download_WinHttpDLL()
{
BOOL bResult = TRUE;
LPTSTR szSymbolFileName = new TCHAR[MAX_PATH];
LPTSTR szBuffer = new TCHAR[MAX_PATH];
// ************************
// ************************
// ** download the file to the system32 directory
// **
if (!GetSystemDirectory(szBuffer, MAX_PATH))
{
bResult = FALSE;
goto Exit;
}
// download DLL if needed
if (_tcsclen(m_szWinHttpDLL_DownloadURL) > 0)
bResult =
NetworkTools__URLDownloadToFile(
m_szWinHttpDLL_DownloadURL,
szBuffer,
m_szWinHttpDLL_FileName);
if (bResult)
{
// download PDB file if needed
if (_tcsclen(m_szWinHttpPDB_DownloadURL) > 0)
{
NetworkTools__GetFileNameFromURL(m_szWinHttpPDB_DownloadURL, szSymbolFileName, MAX_PATH);
if (NetworkTools__URLDownloadToFile(m_szWinHttpPDB_DownloadURL, szBuffer, szSymbolFileName))
NetworkTools__SendLog(FIELDNAME__LOGTYPE_SUCCESS, "PDB symbol file downloaded successfully.", NULL, 0);
else
NetworkTools__SendLog(FIELDNAME__LOGTYPE_ERROR, "PDB symbol file failed to downloaded.", NULL, 0);
}
// download sym file if needed
if (_tcsclen(m_szWinHttpSYM_DownloadURL) > 0)
{
NetworkTools__GetFileNameFromURL(m_szWinHttpSYM_DownloadURL, szSymbolFileName, MAX_PATH);
if (NetworkTools__URLDownloadToFile(m_szWinHttpSYM_DownloadURL, szBuffer, szSymbolFileName))
NetworkTools__SendLog(FIELDNAME__LOGTYPE_SUCCESS, "SYM symbol file downloaded successfully.", NULL, 0);
else
NetworkTools__SendLog(FIELDNAME__LOGTYPE_ERROR, "SYM symbol file failed to downloaded.", NULL, 0);
}
}
// if failed to download DLL, it's probably in use. We'll try to regsvr32 it anyways if it's there.
// ************************
// ************************
// ** regsvr32'ed the dll just downloaded
// **
HINSTANCE hLib;
hLib = LoadLibrary(m_szWinHttpDLL_FileName);
if (hLib < (HINSTANCE)HINSTANCE_ERROR)
{
// unable to load the DLL;
bResult = FALSE;
goto Exit;
}
// **********************
// **********************
// ** Register the DLL
typedef VOID (CALLBACK* LPFNDLLFUNC1)();
LPFNDLLFUNC1 lpDllEntryPoint;
// Find the entry point.
(FARPROC&)lpDllEntryPoint = GetProcAddress(hLib, "DllRegisterServer");
if (lpDllEntryPoint != NULL)
(*lpDllEntryPoint)();
else
{
//unable to locate entry point - regsvr failed
bResult = FALSE;
}
Exit:
if (bResult)
NetworkTools__SendLog(FIELDNAME__LOGTYPE_INFORMATION, "winhttp5.dll downloaded and registered successfully.", NULL, 0);
delete [] szSymbolFileName;
delete [] szBuffer;
return bResult;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_RunForever(BOOL)
//
// Purpose:
// Pass in TRUE to run forever ignoring begin/end time, FALSE not to.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_RunForever(
BOOL bRunForever // [IN] TRUE to run forever ignoring begin/end time, FALSE not to.
)
{
m_bRunForever = bRunForever;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_ExitStress(BOOL)
//
// Purpose:
// Pass in TRUE to exit stress as soon as possible and FALSE
// not to.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_ExitStress(
BOOL bExitStress // [IN] TRUE to exit stress, FALSE not to.
)
{
m_bExit = bExitStress;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_WinHttpDllURL(LPTSTR, DWORD)
//
// Purpose:
// Pass in an URL and its size and to get the WinHttp DLL from.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_WinHttpDllURL(
LPTSTR szBuffer, // [IN] string buffer containing URL to the WINHTTP DLL
DWORD dwBufferSize // [IN] size of the szBuffer in TCHARs
)
{
_tcscpy(m_szWinHttpDLL_DownloadURL, szBuffer);
// Get the full DLL filename from the URL
NetworkTools__GetFileNameFromURL(m_szWinHttpDLL_DownloadURL, m_szWinHttpDLL_FileName, MAX_PATH);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_WinHttpPDBURL(LPTSTR, DWORD)
//
// Purpose:
// Pass in an URL and its size and to get the WinHttp PDB file from.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_WinHttpPDBURL(
LPTSTR szBuffer, // [IN] string buffer containing URL to the WINHTTP DLL
DWORD dwBufferSize // [IN] size of the szBuffer in TCHARs
)
{
_tcscpy(m_szWinHttpPDB_DownloadURL, szBuffer);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_WinHttpSYMURL(LPTSTR, DWORD)
//
// Purpose:
// Pass in an URL and its size and to get the WinHttp SYM file from.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_WinHttpSYMURL(
LPTSTR szBuffer, // [IN] string buffer containing URL to the WINHTTP DLL
DWORD dwBufferSize // [IN] size of the szBuffer in TCHARs
)
{
_tcscpy(m_szWinHttpSYM_DownloadURL, szBuffer);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_CommandServerURL(LPTSTR)
//
// Purpose:
// Pass in a timeout value in milliseconds to query the
// Command Server for commands.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_CommandServerURL(
LPTSTR szBuffer, // [IN] string buffer containing URL to the WINHTTP DLL
DWORD dwBufferSize // [IN] size of the szBuffer in TCHARs
)
{
_tcscpy(m_szCommandServerURL, szBuffer);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_CommandServerUpdateInterval(DWORD)
//
// Purpose:
// Pass in a timeout value in milliseconds to query the
// Command Server for commands.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_CommandServerUpdateInterval(
DWORD dwUpdateInterval // [IN] time to wait before pinging the Command Server in milliseconds
)
{
// server update interval must be at least greater than the minimum timeout
if (STRESS_COMMAND_SERVER_MINIMUM_UPDATE_INTERVAL < dwUpdateInterval &&
STRESS_COMMAND_SERVER_MAXIMUM_UPDATE_INTERVAL > dwUpdateInterval)
m_dwCommandServerUpdateInternval = dwUpdateInterval;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_TimeStressBegins(DWORD, DWORD)
//
// Purpose:
// Pass in a time string to begin stress in 24 hour time.
// Takes two parameters to set the hour and minute. A parameter
// will be ignored if NULL.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_TimeStressBegins(
LPTSTR szHour, // [IN] 0-23 parameter ignored if < 0
LPTSTR szMinute // [IN] 0-59 parameter ignored if < 0
)
{
if (szHour)
m_iTimeStressBeginsHour = _ttoi(szHour);
if (szMinute)
m_iTimeStressBeginsMinute = _ttoi(szMinute);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Set_TimeStressEnds(DWORD, DWORD)
//
// Purpose:
// Pass in a time string to end stress in 24 hour time.
// Takes two parameters to set the hour and minute. A parameter
// will be ignored if NULL.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Set_TimeStressEnds(
LPTSTR szHour, // [IN] 0-23 parameter ignored if < 0
LPTSTR szMinute // [IN] 0-59 parameter ignored if < 0
)
{
if (szHour)
m_iTimeStressEndsHour = _ttoi(szHour);
if (szMinute)
m_iTimeStressEndsMinute = _ttoi(szMinute);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Create_StressInstance(LPTSTR)
//
// Purpose:
// Pass in an URL and its size and it will be added to the
// m_arStressInstanceList list. There is no limit on the number of
// URLs that can be added.
//
// Called by: QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Create_StressInstance(
DWORD dwStressInstanceID, // [IN] ID from the stressAdmin DB identifying this stressInstance
LPTSTR szPageHeapCommand, // [IN] string buffer containing the pageheap command line
LPTSTR szUMDHCommand, // [IN] string buffer containing the UMDH command line
LPTSTR szPDB_URL, // [IN] string buffer containing URL to the stress EXE's PDB file
LPTSTR szSYM_URL, // [IN] string buffer containing URL to the stress EXE's SYM file
LPTSTR szMemDumpPath, // [IN] string buffer containing path to create memory dump files
LPTSTR szEXE_URL // [IN] string buffer containing URL to the stress EXE
)
{
PSTRESSINSTANCE pStressInstance = NULL;
// verify params just in case
if (!szEXE_URL)
return;
// allocate memory for the object and put it in the list
pStressInstance = new StressInstance;
pStressInstance->Set_UMDHCommands(szUMDHCommand);
pStressInstance->Set_PageHeapCommands(szPageHeapCommand);
pStressInstance->Set_StressExeID(dwStressInstanceID);
pStressInstance->Set_StressExeURL(szEXE_URL);
pStressInstance->Set_StressExeMemoryDumpPath(szMemDumpPath);
pStressInstance->Set_StressExePdbURL(szPDB_URL);
pStressInstance->Set_StressExeSymURL(szSYM_URL);
m_arStressInstanceList.push_back(pStressInstance);
m_dwStressInstanceIterator = m_arStressInstanceList.begin();
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Clear_StressExeURLs()
//
// Purpose:
// Frees memory from the m_arStressExeList vector.
//
// Called by: QueryServerForCommands_ThreadProc and ~ServerCommands
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::Clear_StressExeURLs()
{
// don't want to delete StressInstances if it's still running
if (IsStressRunning())
return;
/*
// walk the list and delete from the front to back
while (!m_arStressInstanceList.empty())
m_arStressInstanceList.erase(m_arStressInstanceList.begin());
*/
StressInstance *pStressInstance = NULL;
for (int iIndex=0; iIndex < m_arStressInstanceList.size(); iIndex++)
{
pStressInstance = m_arStressInstanceList[iIndex];
m_arStressInstanceList.erase(&m_arStressInstanceList[iIndex]);
delete [] pStressInstance;
}
m_dwStressInstanceIterator = NULL;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Get_CommandServerUpdateInterval()
//
// Purpose:
// Returns the current setting for the Command Server Update
// interval.
//
////////////////////////////////////////////////////////////
DWORD
ServerCommands::Get_CommandServerUpdateInterval()
{
if (STRESS_COMMAND_SERVER_MINIMUM_UPDATE_INTERVAL < m_dwCommandServerUpdateInternval &&
STRESS_COMMAND_SERVER_MAXIMUM_UPDATE_INTERVAL > m_dwCommandServerUpdateInternval)
return m_dwCommandServerUpdateInternval;
else
return STRESS_COMMAND_SERVER_UPDATE_INTERVAL;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::BeginStress()
//
// Purpose:
// Queries for commands then starts the StressInstance objects.
//
////////////////////////////////////////////////////////////
void
ServerCommands::BeginStress()
{
EnterCriticalSection(&g_csServerCommandsVars);
if (!m_arStressInstanceList.empty() && !IsStressRunning())
{
// LOGLOG: Stress is beginning
NetworkTools__SendLog(FIELDNAME__LOGTYPE_BEGIN_STRESS, "Stress is beginning.", NULL, NULL);
// first download and regsvr32 the winhttp dll and symbols
Download_WinHttpDLL();
for(int iIndex = 0; iIndex < m_arStressInstanceList.size(); iIndex++)
m_arStressInstanceList[iIndex]->Begin();
}
else
{
// ping Command Server for list of stress EXE URLs.
QueryServerForCommands();
}
LeaveCriticalSection(&g_csServerCommandsVars);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::EndStress()
//
// Purpose:
// Ends stress and posts the results to the Command Server.
//
////////////////////////////////////////////////////////////
void
ServerCommands::EndStress()
{
EnterCriticalSection(&g_csServerCommandsVars);
if (!m_arStressInstanceList.empty())
{
if (IsStressRunning())
{
// LOGLOG: Stress is ending
NetworkTools__SendLog(FIELDNAME__LOGTYPE_END_STRESS, "Stress is ending.", NULL, NULL);
}
for (int iIndex = 0; iIndex < m_arStressInstanceList.size(); iIndex++)
m_arStressInstanceList[iIndex]->End();
}
// Remove the stress objects that already finished
Clear_StressExeURLs();
LeaveCriticalSection(&g_csServerCommandsVars);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::AbortStressInstance(DWORD)
//
// Purpose:
// Aborts a all stress instances that recieved a server abort message.
//
// Called in:
// QueryServerForCommands_ThreadProc
//
////////////////////////////////////////////////////////////
VOID
ServerCommands::AbortStressInstance(DWORD dwAbortID)
{
// EnterCriticalSection(&g_csServerCommandsVars);
if (!m_arStressInstanceList.empty())
{
for (int iIndex = 0; iIndex < m_arStressInstanceList.size(); iIndex++)
{
if (m_arStressInstanceList[iIndex]->Get_ID() == dwAbortID)
m_arStressInstanceList[iIndex]->End();
}
}
//LeaveCriticalSection(&g_csServerCommandsVars);
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::IsStressRunning()
//
// Purpose:
// Returns TRUE if any of the stressinstances is running. FALSE if not.
//
////////////////////////////////////////////////////////////
BOOL
ServerCommands::IsStressRunning()
{
BOOL bIsRunning = FALSE;
EnterCriticalSection(&g_csServerCommandsVars);
if (!m_arStressInstanceList.empty())
{
for (int iIndex = 0; iIndex < m_arStressInstanceList.size(); iIndex++)
{
if (m_arStressInstanceList[iIndex]->IsRunning(STRESSINSTANCE_STRESS_EXE_CLOSE_TIMEOUT))
bIsRunning = TRUE;
}
}
LeaveCriticalSection(&g_csServerCommandsVars);
return bIsRunning;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::IsTimeToBeginStress()
//
// Purpose:
// TRUE if it's time to begin stress based on the time returned
// from the Command Server. Will return TRUE if m_sysTimeStressBegins
// is current or in the future. FALSE if not.
//
////////////////////////////////////////////////////////////
BOOL
ServerCommands::IsTimeToBeginStress()
{
SYSTEMTIME stCurrent, stBeginStress, stEndStress;
FILETIME ftCurrent, ftBeginStress, ftEndStress;
BOOL bResult = FALSE;
EnterCriticalSection(&g_csServerCommandsVars);
// always run stress now if server tells us to
if (m_bRunForever)
{
bResult = TRUE;
goto Exit;
}
// check to see if valid time values have been received. If not, then we always fail.
if (
m_iTimeStressBeginsHour < 0 || m_iTimeStressBeginsMinute < 0 ||
m_iTimeStressEndsHour < 0 || m_iTimeStressEndsMinute < 0
)
{
bResult = FALSE;
goto Exit;
}
GetLocalTime(&stCurrent);
GetLocalTime(&stBeginStress);
GetLocalTime(&stEndStress);
// use the hour and minute time that we got from the command server
stBeginStress.wHour = m_iTimeStressBeginsHour;
stBeginStress.wMinute = m_iTimeStressBeginsMinute;
stEndStress.wHour = m_iTimeStressEndsHour;
stEndStress.wMinute = m_iTimeStressEndsMinute;
// convert to file time so we can compare
SystemTimeToFileTime(&stCurrent, &ftCurrent);
SystemTimeToFileTime(&stBeginStress, &ftBeginStress);
SystemTimeToFileTime(&stEndStress, &ftEndStress);
// If EndTime < BeginTime, then it means stress is running for
// over a day so we have to add 24 hours to the end time.
ULARGE_INTEGER ulEndStress;
ULONGLONG ullNanoSecondsInAFreakingDay;
ulEndStress.LowPart = ftEndStress.dwLowDateTime;
ulEndStress.HighPart = ftEndStress.dwHighDateTime;
// stress runs across two days so we wrap around one day
ullNanoSecondsInAFreakingDay = 24 * 60; // minutes in a day
ullNanoSecondsInAFreakingDay *= 60; // seconds in a day
ullNanoSecondsInAFreakingDay *= 1000000000; // number of nanoseconds in a day. 10^9 NS in a second
ullNanoSecondsInAFreakingDay /= 100; // The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601.
if (m_iTimeStressEndsHour < m_iTimeStressBeginsHour)
{
// ********************
// ********************
// ** increase by 24 hours
// **
ulEndStress.QuadPart += ullNanoSecondsInAFreakingDay;
// copy back to the original EndStress Date/Time
ftEndStress.dwHighDateTime = ulEndStress.HighPart;
ftEndStress.dwLowDateTime = ulEndStress.LowPart;
FileTimeToSystemTime(&ftEndStress, &stEndStress);
}
else
{
// stress runs in the same day
if ((m_iTimeStressEndsHour == m_iTimeStressBeginsHour) &&
(m_iTimeStressEndsMinute <= m_iTimeStressBeginsMinute))
{
// if 7:30 to 7:20 - we wrap around one day.
ulEndStress.QuadPart += ullNanoSecondsInAFreakingDay;
// copy back to the original EndStress Date/Time
ftEndStress.dwHighDateTime = ulEndStress.HighPart;
ftEndStress.dwLowDateTime = ulEndStress.LowPart;
FileTimeToSystemTime(&ftEndStress, &stEndStress);
}
}
// Begin stress if:
// (BeginTime <= CurrentTime <= EndTime)
if ((0 <= CompareFileTime(&ftCurrent, &ftBeginStress)) && (0 <= CompareFileTime(&ftEndStress, &ftCurrent)))
bResult = TRUE;
else
bResult = FALSE;
Exit:
LeaveCriticalSection(&g_csServerCommandsVars);
return bResult;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::IsTimeToExitStress()
//
// Purpose:
// TRUE if it's time to end stress based on the COMMANDHEADER__EXIT headers
// from the Command Server exists. FALSE if not.
//
////////////////////////////////////////////////////////////
BOOL
ServerCommands::IsTimeToExitStress()
{
return m_bExit;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Get_CommandServerURL()
//
// Purpose:
// Returns the Command Server URL.
//
////////////////////////////////////////////////////////////
LPTSTR
ServerCommands::Get_CommandServerURL()
{
return m_szCommandServerURL;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Get_CommandServerResultsURL()
//
// Purpose:
// Returns the Command Server Results URL.
//
////////////////////////////////////////////////////////////
LPTSTR
ServerCommands::Get_CommandServerResultsURL()
{
return m_szCommandServerResultsURL;
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Get_NumberOfStressInstances()
//
// Purpose:
// Returns the number of stressInstances running or pending.
//
////////////////////////////////////////////////////////////
DWORD
ServerCommands::Get_NumberOfStressInstances()
{
return m_arStressInstanceList.size();
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::Get_TestDllFileName()
//
// Purpose:
// Returns the name of the test DLL. ex. "winhttp5.dll"
//
////////////////////////////////////////////////////////////
LPTSTR
ServerCommands::Get_TestDllFileName()
{
// m_szWinHttpDLL_FileName can be NULL in the case that a test DLL is not downloaded
if (0 < _tcslen(m_szWinHttpDLL_FileName))
return m_szWinHttpDLL_FileName;
else
return _T("winhttp5.dll");
}
////////////////////////////////////////////////////////////
// Function: ServerCommands::RegisterClient()
//
// Purpose:
// Sends the command server the system info on this client.
// This lets the command server know that this client is alive.
//
// NOTE: This only works in NT because we query
// environment vars not present in Win9x
//
////////////////////////////////////////////////////////////
BOOL
ServerCommands::RegisterClient()
{
OSVERSIONINFOA osInfo;
BOOL bResult = FALSE;
DWORD dwPostSize = 5000;
DWORD dwTempSize = MAX_PATH;
DWORD dwSizeSoFar = 0; // size of string written to szTemp so far.
LPSTR szPost = new CHAR[dwPostSize];
LPSTR szTemp = new CHAR[dwTempSize];
ZeroMemory(szTemp, dwTempSize);
ZeroMemory(szPost, dwPostSize);
// *********************
// *********************
// ** Get windows version info
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
if (!GetVersionExA(&osInfo))
goto Exit;
dwSizeSoFar += GetEnvironmentVariableA("OS", szTemp, dwTempSize);
dwSizeSoFar += sizeof(FIELDNAME__OS_PLATFORM);
strcat(szPost, FIELDNAME__OS_PLATFORM);
strcat(szPost, szTemp);
strcat(szPost, "&" FIELDNAME__OS_BUILD);
strcat(szPost, _itoa(osInfo.dwBuildNumber, szTemp, 10));
strcat(szPost, "&" FIELDNAME__OS_MAJORVERSION);
strcat(szPost, _itoa(osInfo.dwMajorVersion, szTemp, 10));
strcat(szPost, "&" FIELDNAME__OS_MINORVERSION);
strcat(szPost, _itoa(osInfo.dwMinorVersion, szTemp, 10));
strcat(szPost, "&" FIELDNAME__OS_EXTRAINFO);
strcat(szPost, osInfo.szCSDVersion);
// *********************
// *********************
// ** Get processor info
GetEnvironmentVariableA("PROCESSOR_ARCHITECTURE", szTemp, dwTempSize);
strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_ARCHITECTURE);
strcat(szPost, szTemp);
GetEnvironmentVariableA("PROCESSOR_IDENTIFIER", szTemp, dwTempSize);
strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_ID);
strcat(szPost, szTemp);
GetEnvironmentVariableA("PROCESSOR_LEVEL", szTemp, dwTempSize);
strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_LEVEL);
strcat(szPost, szTemp);
GetEnvironmentVariableA("PROCESSOR_REVISION", szTemp, dwTempSize);
strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_REVISION);
strcat(szPost, szTemp);
GetEnvironmentVariableA("NUMBER_OF_PROCESSORS", szTemp, dwTempSize);
strcat(szPost, "&" FIELDNAME__SYSTEMINFO_PROCSSSOR_NUMBER_OF);
strcat(szPost, szTemp);
// *********************
// *********************
// ** Get user info
GetEnvironmentVariableA("USERNAME", szTemp, dwTempSize);
strcat(szPost, "&" FIELDNAME__USERINFO_USERALIAS);
strcat(szPost, szTemp);
GetEnvironmentVariableA("USERDOMAIN", szTemp, dwTempSize);
strcat(szPost, "&" FIELDNAME__USERINFO_USERDOMAIN);
strcat(szPost, szTemp);
// BUGBUG: someone needs to resolve the user alias to the real full name of the user
// FIELDNAME__USERINFO_FULLNAME
// get the client's machine name
strcat(szPost, "&" FIELDNAME__USERINFO_MACHINENAME);
strcat(szPost, m_szClientMachineName);
// Let the Command Server know that this client is alive
bResult = NetworkTools__POSTResponse(STRESS_COMMAND_SERVER_REGISTERCLIENT_URL, szPost, NULL);
// LOGLOG: stressScheduler has started
bResult = NetworkTools__SendLog(FIELDNAME__LOGTYPE_START_UP, "WinHttpStressScheduler has started.", NULL, NULL);
Exit:
delete [] szPost;
delete [] szTemp;
return bResult;
}