579 lines
15 KiB
C++
579 lines
15 KiB
C++
//
|
|
// MODULE: StateInfo.cpp
|
|
//
|
|
// PURPOSE: Contains sniffing, network and node information. Also is used
|
|
// by the Launch module to start the container application.
|
|
//
|
|
// Basically, this is how the Launch Server packages up info for the
|
|
// Local TShoot OCX, launches either IE or HTML Help System to a page
|
|
// containing the Local TShoot OCX, and handshakes with the Local TShoot OCX
|
|
// to pass that information
|
|
//
|
|
// Note that CSMStateInfo::GetShooterStates() is called by the
|
|
// Local TShoot OCX to pick up the CItem object which contains
|
|
// the packaged-up info.
|
|
//
|
|
// PROJECT: Local Troubleshooter Launcher for the Device Manager
|
|
//
|
|
// COMPANY: Saltmine Creative, Inc. (206)-633-4743 support@saltmine.com
|
|
//
|
|
// AUTHOR: Richard Meadows
|
|
// COMMENTS BY: Joe Mabel
|
|
//
|
|
// ORIGINAL DATE: 2-26-98
|
|
//
|
|
//
|
|
// Version Date By Comments
|
|
//--------------------------------------------------------------------
|
|
// V0.1 - RM Original
|
|
///////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "atlbase.h"
|
|
#include "StateInfo.h"
|
|
|
|
#include "TSLError.h"
|
|
#include "ComGlobals.h"
|
|
|
|
#include "Registry.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
//#include <fstream.h>
|
|
#include <strstrea.h>
|
|
|
|
////////////////////////////////////////////////////////
|
|
// CItem :
|
|
// Data structure for pseudo HTTP "get" in launching Local Troubleshooters
|
|
//
|
|
|
|
CItem::CItem()
|
|
{
|
|
// initializing this is exactly the same as reinitializing.
|
|
ReInit();
|
|
}
|
|
|
|
void CItem::ReInit()
|
|
{
|
|
memset(m_aszCmds, NULL, SYM_LEN * NODE_COUNT);
|
|
memset(m_aszVals, NULL, SYM_LEN * NODE_COUNT);
|
|
m_cNodesSet = 0;
|
|
_tcscpy(m_szProblemDef, _T("TShootProblem"));
|
|
_tcscpy(m_szTypeDef, _T("type"));
|
|
m_szPNPDeviceID[0] = NULL;
|
|
m_szGuidClass[0] = NULL;
|
|
m_szContainerPathName[0] = NULL;
|
|
m_szWebPage[0] = NULL;
|
|
m_szSniffScriptFile[0] = NULL;
|
|
m_eLaunchRegime = launchIndefinite;
|
|
m_szMachineID[0] = NULL;
|
|
m_szDeviceInstanceID[0] = NULL;
|
|
|
|
#ifdef _DEBUG
|
|
|
|
// There are some other things you need to comment out in GetShooterStates
|
|
// to allow debugging this service from a tshoot.ocx debug sesstion.
|
|
/*
|
|
_tcscpy(m_aszCmds[0], m_szTypeDef);
|
|
_tcscpy(m_aszVals[0], _T("ras"));
|
|
_tcscpy(m_aszCmds[1], m_szProblemDef);
|
|
_tcscpy(m_aszVals[1], _T("CnntCnnctAftrDlngWthRS"));
|
|
_tcscpy(m_aszCmds[2], _T("SoftwareCompression"));
|
|
_tcscpy(m_aszVals[2], _T("0"));
|
|
m_cNodesSet = 1;
|
|
*/
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
void CItem::Clear()
|
|
{
|
|
memset(m_aszCmds, NULL, SYM_LEN * NODE_COUNT);
|
|
memset(m_aszVals, NULL, SYM_LEN * NODE_COUNT);
|
|
m_cNodesSet = 0;
|
|
_tcscpy(m_szProblemDef, _T("TShootProblem"));
|
|
_tcscpy(m_szTypeDef, _T("type"));
|
|
m_szPNPDeviceID[0] = NULL;
|
|
m_szGuidClass[0] = NULL;
|
|
m_szContainerPathName[0] = NULL;
|
|
m_szWebPage[0] = NULL;
|
|
m_szSniffScriptFile[0] = NULL;
|
|
m_eLaunchRegime = launchIndefinite;
|
|
return;
|
|
}
|
|
|
|
// ----------- Routines to build command/value pairs ------------------
|
|
// see documentation of m_aszCmds, m_aszVals for further explanation
|
|
|
|
void CItem::SetNetwork(LPCTSTR szNetwork)
|
|
{
|
|
if (NULL != szNetwork && NULL != szNetwork[0])
|
|
{
|
|
_tcscpy(m_aszCmds[0], m_szTypeDef);
|
|
_tcsncpy(m_aszVals[0], szNetwork, SYM_LEN);
|
|
}
|
|
else
|
|
{
|
|
m_aszCmds[0][0] = NULL;
|
|
m_aszVals[0][0] = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CItem::SetProblem(LPCTSTR szProblem)
|
|
{
|
|
if (NULL != szProblem && NULL != szProblem[0])
|
|
{
|
|
_tcscpy(m_aszCmds[1], m_szProblemDef);
|
|
_tcsncpy(m_aszVals[1], szProblem, SYM_LEN);
|
|
}
|
|
else
|
|
{
|
|
m_aszCmds[1][0] = NULL;
|
|
m_aszVals[1][0] = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CItem::SetNode(LPCTSTR szNode, LPCTSTR szState)
|
|
{
|
|
if (NULL != szNode && NULL != szNode[0]
|
|
&& NULL != szState && NULL != szState[0])
|
|
{
|
|
_tcsncpy(m_aszCmds[m_cNodesSet + 2], szNode, SYM_LEN);
|
|
_tcsncpy(m_aszVals[m_cNodesSet + 2], szState, SYM_LEN);
|
|
m_cNodesSet++;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// ----------- Routines to query command/value pairs ------------------
|
|
// See documentation of m_aszCmds, m_aszVals for further explanation
|
|
|
|
// returns true if network has been set
|
|
// On success, OUTPUT *pszCmd is "type", *pszVal is network name
|
|
bool CItem::GetNetwork(LPTSTR *pszCmd, LPTSTR *pszVal)
|
|
{
|
|
*pszCmd = m_szTypeDef;
|
|
*pszVal = m_aszVals[0];
|
|
return *m_aszVals[0] != NULL;
|
|
}
|
|
|
|
// returns true if problem node has been set
|
|
// On success, OUTPUT *pszCmd is "TShootProblem", *pszVal is problem node's symbolic name
|
|
bool CItem::GetProblem(LPTSTR *pszCmd, LPTSTR *pszVal)
|
|
{
|
|
*pszCmd = m_szProblemDef;
|
|
*pszVal = m_aszVals[1];
|
|
return *m_aszVals[1] != NULL;;
|
|
}
|
|
|
|
// output the iNodeC-th non-problem node for which a state has been set.
|
|
// On success, OUTPUT *pszCmd is symbolic node name, *pszVal is state
|
|
// returns true if at least iNodeC non-problem nodes have been set
|
|
bool CItem::GetNodeState(int iNodeC, LPTSTR *pszCmd, LPTSTR *pszVal)
|
|
{
|
|
if (iNodeC >= m_cNodesSet)
|
|
return false;
|
|
*pszCmd = m_aszCmds[iNodeC + 2];
|
|
*pszVal = m_aszVals[iNodeC + 2];
|
|
return true;
|
|
}
|
|
|
|
// ----------- Routines to query whether we know a network ------------
|
|
// ----------- & problem node to launch to ----------------------------
|
|
// See documentation of m_aszCmds, m_aszVals for further explanation
|
|
|
|
// NetworkSet returns true if we know which troubleshooter to launch.
|
|
bool CItem::NetworkSet()
|
|
{
|
|
return NULL != m_aszVals[0][0];
|
|
}
|
|
// ProblemSet returns true if we know which problem to choose.
|
|
bool CItem::ProblemSet()
|
|
{
|
|
return NULL != m_aszVals[1][0];
|
|
}
|
|
|
|
// --------- Interface to other member variables recponsible for launching -----------
|
|
|
|
void CItem::SetLaunchRegime(ELaunchRegime eLaunchRegime)
|
|
{
|
|
m_eLaunchRegime = eLaunchRegime;
|
|
}
|
|
|
|
void CItem::SetContainerPathName(TCHAR szContainerPathName[MAX_PATH])
|
|
{
|
|
if (NULL != szContainerPathName && NULL != szContainerPathName[0])
|
|
_tcscpy(m_szContainerPathName, szContainerPathName);
|
|
else
|
|
m_szContainerPathName[0] = NULL;
|
|
return;
|
|
}
|
|
|
|
void CItem::SetWebPage(TCHAR szWebPage[MAX_PATH])
|
|
{
|
|
if (NULL != szWebPage && NULL != szWebPage[0])
|
|
_tcscpy(m_szWebPage, szWebPage);
|
|
else
|
|
m_szWebPage[0] = NULL;
|
|
return;
|
|
}
|
|
|
|
void CItem::SetSniffScriptFile(TCHAR szSniffScriptFile[MAX_PATH])
|
|
{
|
|
if (NULL != szSniffScriptFile && NULL != szSniffScriptFile[0])
|
|
_tcscpy(m_szSniffScriptFile, szSniffScriptFile);
|
|
else
|
|
m_szSniffScriptFile[0] = NULL;
|
|
return;
|
|
}
|
|
|
|
void CItem::SetSniffStandardFile(TCHAR szSniffStandardFile[MAX_PATH])
|
|
{
|
|
if (NULL != szSniffStandardFile && NULL != szSniffStandardFile[0])
|
|
_tcscpy(m_szSniffStandardFile, szSniffStandardFile);
|
|
else
|
|
m_szSniffStandardFile[0] = NULL;
|
|
return;
|
|
}
|
|
|
|
ELaunchRegime CItem::GetLaunchRegime()
|
|
{
|
|
return m_eLaunchRegime;
|
|
}
|
|
|
|
inline TCHAR* CItem::GetContainerPathName()
|
|
{
|
|
return m_szContainerPathName;
|
|
}
|
|
|
|
inline TCHAR* CItem::GetWebPage()
|
|
{
|
|
return m_szWebPage;
|
|
}
|
|
|
|
inline TCHAR* CItem::GetSniffScriptFile()
|
|
{
|
|
return m_szSniffScriptFile;
|
|
}
|
|
|
|
inline TCHAR* CItem::GetSniffStandardFile()
|
|
{
|
|
return m_szSniffStandardFile;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// CSMStateInfo :
|
|
// State information on MSBN Troubleshooters
|
|
//
|
|
|
|
CSMStateInfo::CSMStateInfo()
|
|
{
|
|
m_csGlobalMemory.Init();
|
|
m_csSingleLaunch.Init();
|
|
return;
|
|
}
|
|
|
|
CSMStateInfo::~CSMStateInfo()
|
|
{
|
|
m_csGlobalMemory.Term();
|
|
m_csSingleLaunch.Term();
|
|
return;
|
|
}
|
|
|
|
// TestPut: Simply copies item to m_Item.
|
|
void CSMStateInfo::TestPut(CItem &item)
|
|
{
|
|
m_csGlobalMemory.Lock();
|
|
m_Item = item;
|
|
m_csGlobalMemory.Unlock();
|
|
return;
|
|
}
|
|
|
|
// TestGet: Simply copies m_Item to item.
|
|
void CSMStateInfo::TestGet(CItem &item)
|
|
{
|
|
m_csGlobalMemory.Lock();
|
|
item = m_Item;
|
|
m_csGlobalMemory.Unlock();
|
|
return;
|
|
}
|
|
|
|
// Copy the item to the global memory and launch a process based on the command.
|
|
// Copying the item to global memory is here because the item is what tells the
|
|
// launched local troubleshooter what belief network etc. it is being launched to.
|
|
// Once we unlock global memory, the Local Troubleshooter OCX can read that item
|
|
// and act on it.
|
|
BOOL CSMStateInfo::CreateContainer(CItem &item, LPTSTR szCommand)
|
|
{
|
|
BOOL bOk = TRUE;
|
|
HRESULT hRes = S_OK;
|
|
STARTUPINFO startup;
|
|
PROCESS_INFORMATION process;
|
|
|
|
memset(&startup, NULL, sizeof(STARTUPINFO));
|
|
startup.cb = sizeof(STARTUPINFO);
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
m_csGlobalMemory.Lock();
|
|
m_Item = item;
|
|
|
|
bOk = CreateProcess(NULL, szCommand, NULL, NULL, FALSE, 0, NULL, NULL,
|
|
&startup, &process);
|
|
CloseHandle(process.hThread);
|
|
CloseHandle(process.hProcess);
|
|
|
|
m_csGlobalMemory.Unlock();
|
|
return bOk;
|
|
}
|
|
|
|
//
|
|
// Copy network_sniff.htm to tssniffAsk.htm if the former exists
|
|
// Create (modify) tssniffAsk.htm to be a sniffing stub otherwise
|
|
//
|
|
BOOL CSMStateInfo::CopySniffScriptFile(CItem &item)
|
|
{
|
|
TCHAR* szSniffScriptFile = item.GetSniffScriptFile();
|
|
TCHAR* szSniffStandardFile = item.GetSniffStandardFile();
|
|
|
|
if (!*szSniffScriptFile) // no network specific sniff file
|
|
{
|
|
// szSniffScriptFile contains tssniffAsk.htm
|
|
// it means that we have to form this file as an empty stub
|
|
ostrstream fileSniffScript;
|
|
|
|
HANDLE hFile = ::CreateFile(szSniffStandardFile,
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL, // no security attributes
|
|
CREATE_ALWAYS,
|
|
FILE_FLAG_RANDOM_ACCESS,
|
|
NULL // handle to template file
|
|
);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
// form html file - part preceding script
|
|
fileSniffScript << "<HTML>" << endl;
|
|
fileSniffScript << "<HEAD>" << endl;
|
|
fileSniffScript << "<TITLE>GTS LOCAL</TITLE>" << endl;
|
|
fileSniffScript << "</HEAD>" << endl;
|
|
fileSniffScript << "<SCRIPT LANGUAGE=\"VBSCRIPT\">" << endl;
|
|
fileSniffScript << "<!--" << endl;
|
|
|
|
// form global function
|
|
fileSniffScript << "function PerformSniffing()" << endl;
|
|
fileSniffScript << "end function" << endl;
|
|
|
|
// form html file - part after script
|
|
fileSniffScript << "-->" << endl;
|
|
fileSniffScript << "</SCRIPT>" << endl;
|
|
fileSniffScript << "<BODY BGCOLOR=\"#FFFFFF\">" << endl;
|
|
fileSniffScript << "</BODY>" << endl;
|
|
fileSniffScript << "</HTML>" << endl;
|
|
fileSniffScript << ends;
|
|
|
|
char* str = fileSniffScript.str();
|
|
DWORD read;
|
|
|
|
if (!::WriteFile(hFile, str, strlen(str), &read, NULL))
|
|
{
|
|
::CloseHandle(hFile);
|
|
fileSniffScript.rdbuf()->freeze(0);
|
|
return false;
|
|
}
|
|
|
|
::CloseHandle(hFile);
|
|
fileSniffScript.rdbuf()->freeze(0);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ::CopyFile(szSniffScriptFile, szSniffStandardFile, false);
|
|
}
|
|
}
|
|
|
|
// Find the container (HTML Help System or IE) and starting web page, launch, wait to
|
|
// see if launch succeeded
|
|
bool CSMStateInfo::GoGo(DWORD dwTimeOut, CItem &item, DWORD *pdwResult)
|
|
{
|
|
bool bResult = true;
|
|
HANDLE hLaunchedEvent = NULL;
|
|
TCHAR szProcess[MAX_PATH];
|
|
TCHAR szWebPage[MAX_PATH];
|
|
LPTSTR pszCommand = NULL;
|
|
int CommandLen;
|
|
DWORD dwError;
|
|
int Count = 34;
|
|
|
|
if (item.GetLaunchRegime() == launchIndefinite ||
|
|
!item.GetContainerPathName()[0] ||
|
|
!item.GetWebPage()[0]
|
|
)
|
|
{
|
|
*pdwResult = TSL_ERROR_ASSERTION;
|
|
return false;
|
|
}
|
|
|
|
do
|
|
{
|
|
_stprintf(item.m_szEventName, _T("TSL_SHOOTER_Event_%ld"), Count);
|
|
if (NULL == (hLaunchedEvent = CreateEvent (NULL, FALSE, FALSE, item.m_szEventName)))
|
|
{
|
|
dwError = GetLastError();
|
|
if (ERROR_ALREADY_EXISTS != dwError)
|
|
{
|
|
*pdwResult = dwError;
|
|
return false;
|
|
}
|
|
}
|
|
} while (NULL == hLaunchedEvent);
|
|
|
|
// Get the path to internet explorer (or HTML Help System).
|
|
_tcscpy(szProcess, item.GetContainerPathName());
|
|
|
|
// Need to know the location and name of the
|
|
// page that asks the service for the CItem
|
|
// information.
|
|
_tcscpy(szWebPage, item.GetWebPage());
|
|
|
|
CommandLen = _tcslen(szProcess) + 1 + _tcslen(szWebPage) + 2;
|
|
pszCommand = new TCHAR[CommandLen];
|
|
if (NULL == pszCommand)
|
|
{
|
|
*pdwResult = TSL_ERROR_OUT_OF_MEMORY;
|
|
return false;
|
|
}
|
|
_tcscpy(pszCommand, szProcess);
|
|
_tcscat(pszCommand, _T(" "));
|
|
_tcscat(pszCommand, szWebPage);
|
|
|
|
m_csSingleLaunch.Lock();
|
|
|
|
// copy to or create tssniffAsk.htm
|
|
if (!CopySniffScriptFile(item))
|
|
{
|
|
*pdwResult = TSL_E_COPY_SNIFF_SCRIPT;
|
|
return false;
|
|
}
|
|
|
|
// CreateContainer copies the item to the global memory and
|
|
// launches the command.
|
|
if (!CreateContainer(item, pszCommand))
|
|
{
|
|
*pdwResult = TSL_E_CREATE_PROC;
|
|
bResult = false;
|
|
}
|
|
else
|
|
{
|
|
if (WAIT_OBJECT_0 == WaitForSingleObject(hLaunchedEvent, dwTimeOut))
|
|
{ // The container has the information.
|
|
*pdwResult = TSL_OK;
|
|
}
|
|
else
|
|
{ // Wait timed out. Don't know if the operation will work or not work.
|
|
*pdwResult = TSL_W_CONTAINER_WAIT_TIMED_OUT;
|
|
}
|
|
}
|
|
m_csSingleLaunch.Unlock();
|
|
|
|
delete [] pszCommand;
|
|
|
|
CloseHandle(hLaunchedEvent);
|
|
return bResult;
|
|
}
|
|
|
|
// Find the container (HTML Help System or IE) and start it up to a URL which is _not_
|
|
// expected to contain Local Troubleshooter, just an arbitrary web page. This should
|
|
// only be used when the launch as such can't work, and we are just trying to give them
|
|
// somewhere to start troubleshooting, typically the home page which lists all
|
|
// trobleshooting belief networks.
|
|
bool CSMStateInfo::GoURL(CItem &item, DWORD *pdwResult)
|
|
{
|
|
bool bResult = true;
|
|
TCHAR szProcess[MAX_PATH];
|
|
TCHAR szWebPage[MAX_PATH];
|
|
LPTSTR pszCommand = NULL;
|
|
int CommandLen;
|
|
|
|
if (item.GetLaunchRegime() != launchDefaultWebPage ||
|
|
!item.GetContainerPathName()[0] ||
|
|
!item.GetWebPage()[0]
|
|
)
|
|
{
|
|
*pdwResult = TSL_ERROR_ASSERTION;
|
|
return false;
|
|
}
|
|
|
|
// Get the path to internet explorer (or HTML Help System).
|
|
_tcscpy(szProcess, item.GetContainerPathName());
|
|
|
|
// Need to know the location and name of the
|
|
// page that asks the service for the CItem
|
|
// information.
|
|
_tcscpy(szWebPage, item.GetWebPage());
|
|
|
|
CommandLen = _tcslen(szProcess) + 1 + _tcslen(szWebPage) + 2;
|
|
pszCommand = new TCHAR[CommandLen];
|
|
if (NULL == pszCommand)
|
|
{
|
|
*pdwResult = TSL_ERROR_OUT_OF_MEMORY;
|
|
return false;
|
|
}
|
|
_tcscpy(pszCommand, szProcess);
|
|
_tcscat(pszCommand, _T(" "));
|
|
_tcscat(pszCommand, szWebPage);
|
|
|
|
// CreateContainer is overkill here, but perfectly OK.
|
|
if (!CreateContainer(item, pszCommand))
|
|
{
|
|
*pdwResult = TSL_E_CREATE_PROC;
|
|
bResult = false;
|
|
}
|
|
|
|
delete [] pszCommand;
|
|
|
|
return bResult;
|
|
}
|
|
|
|
// This function is used by the Local Troubleshooter OCX, not by the Launcher.
|
|
// This is how the Local Troubleshooter knows what troubleshooting network to launch
|
|
// to, as well as any nodes whose states are set.
|
|
// GetShooterStates returns the commands and the number of commands for
|
|
// the Tshoot.ocx.
|
|
// refLaunchState is a member of this instance of the LaunchTS interface.
|
|
//
|
|
HRESULT CSMStateInfo::GetShooterStates(CItem &refLaunchState, DWORD *pdwResult)
|
|
{
|
|
HANDLE hHaveItemEvent;
|
|
// Get a copy of the launch info state stored in this instance.
|
|
// Synchronize with the process that launched the service.
|
|
|
|
m_csGlobalMemory.Lock();
|
|
|
|
if (NULL == (hHaveItemEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, m_Item.m_szEventName)))
|
|
{
|
|
*pdwResult = GetLastError();
|
|
m_csGlobalMemory.Unlock();
|
|
return TSL_E_FAIL;
|
|
}
|
|
|
|
// Get a copy of the state before unlocking the global memory.
|
|
refLaunchState = m_Item;
|
|
// Let the other process continue running.
|
|
|
|
SetEvent(hHaveItemEvent);
|
|
m_csGlobalMemory.Unlock();
|
|
CloseHandle(hHaveItemEvent);
|
|
|
|
*pdwResult = 0;
|
|
return S_OK;
|
|
}
|