|
|
//
// 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 [email protected]
//
// 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; }
|