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.
1001 lines
26 KiB
1001 lines
26 KiB
//
|
|
// MODULE: Launch.cpp
|
|
//
|
|
// PURPOSE: Starts the container that will query the LaunchServ for
|
|
// troubleshooter network and nodes.
|
|
//
|
|
// PROJECT: Local Troubleshooter Launcher for the Device Manager
|
|
//
|
|
// COMPANY: Saltmine Creative, Inc. (206)-633-4743 [email protected]
|
|
//
|
|
// AUTHOR: Richard Meadows
|
|
//
|
|
// ORIGINAL DATE: 2-26-98
|
|
//
|
|
//
|
|
// Version Date By Comments
|
|
//--------------------------------------------------------------------
|
|
// V0.1 - RM Original
|
|
///////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "StateInfo.h"
|
|
|
|
#include "RSSTACK.H"
|
|
|
|
#include "TSMapAbstract.h"
|
|
#include "TSMap.h"
|
|
#include "TSMapClient.h"
|
|
|
|
#include "Launch.h"
|
|
#include "ComGlobals.h"
|
|
#include "TSLError.h"
|
|
#include "Registry.h"
|
|
|
|
#include <rpc.h>
|
|
|
|
#define LAUNCH_WAIT_TIMEOUT 60 * 1000 // One minute wait.
|
|
|
|
#define SZ_WEB_PAGE _T("asklibrary.htm") // name of hardcoded .htm file that contains troubleshooter OCX
|
|
|
|
|
|
// uncomment the following line to turn on Joe's hard-core debugging
|
|
//#define JDEBUG 1
|
|
|
|
#ifdef JDEBUG
|
|
#include <stdio.h>
|
|
// Convert TCHAR *szt to char *sz. *sz should point to a big enough buffer
|
|
// to contain an SNCS version of *szt. count indicates the size of buffer *sz.
|
|
// returns sz (convenient for use in string functions).
|
|
static char* ToSBCS (char * const sz, const TCHAR * szt, size_t count)
|
|
{
|
|
if (sz)
|
|
{
|
|
if (count != 0 && !szt)
|
|
sz[0] = '\0';
|
|
else
|
|
{
|
|
#ifdef _UNICODE
|
|
wcstombs( sz, szt, count );
|
|
#else
|
|
strcpy(sz, szt);
|
|
#endif
|
|
}
|
|
}
|
|
return sz;
|
|
}
|
|
#endif
|
|
|
|
|
|
CLaunch::CLaunch()
|
|
{
|
|
InitFiles();
|
|
InitRequest();
|
|
m_lLaunchWaitTimeOut = LAUNCH_WAIT_TIMEOUT;
|
|
m_bPreferOnline = false;
|
|
}
|
|
|
|
CLaunch::~CLaunch()
|
|
{
|
|
if (m_pMap)
|
|
delete(m_pMap);
|
|
}
|
|
|
|
// This initialization happens exactly once for the object.
|
|
// Once we've looked in the registry and found a file, it isn't going anywhere.
|
|
void CLaunch::InitFiles()
|
|
{
|
|
DWORD dwBufSize;
|
|
CRegKey reg;
|
|
DWORD dwBytesUsed;
|
|
|
|
m_bHaveMapPath = false;
|
|
m_bHaveDefMapFile = false;
|
|
m_bHaveDszPath = false;
|
|
m_szLauncherResources[0] = NULL;
|
|
m_szDefMapFile[0] = NULL;
|
|
m_szLaunchMapFile[0] = NULL;
|
|
m_szDszResPath[0] = NULL;
|
|
m_szMapFile[0] = NULL;
|
|
m_pMap = NULL;
|
|
|
|
if (ERROR_SUCCESS == reg.Open(
|
|
HKEY_LOCAL_MACHINE, SZ_LAUNCHER_ROOT))
|
|
{
|
|
dwBufSize = MAX_PATH;
|
|
TCHAR szLauncherResources[MAX_PATH];
|
|
if (ERROR_SUCCESS == reg.QueryValue(
|
|
szLauncherResources, SZ_GLOBAL_LAUNCHER_RES, &dwBufSize))
|
|
{
|
|
if ('\\' != szLauncherResources[_tcslen(szLauncherResources) - 1])
|
|
_tcscat(szLauncherResources, _T("\\"));
|
|
|
|
dwBufSize = MAX_PATH;
|
|
dwBytesUsed = ExpandEnvironmentStrings(szLauncherResources, m_szLauncherResources, dwBufSize); // The value returned by ExpandEnviromentStrings is larger than the required size.
|
|
|
|
}
|
|
dwBufSize = MAX_PATH;
|
|
TCHAR szDefMapFile[MAX_PATH];
|
|
if (ERROR_SUCCESS == reg.QueryValue(
|
|
szDefMapFile, SZ_GLOBAL_MAP_FILE, &dwBufSize))
|
|
{
|
|
WIN32_FIND_DATA data;
|
|
HANDLE hFind;
|
|
|
|
dwBufSize = MAX_PATH;
|
|
dwBytesUsed = ExpandEnvironmentStrings(szDefMapFile, m_szDefMapFile, dwBufSize); // The value returned by ExpandEnviromentStrings is larger than the required size.
|
|
if (0 != dwBytesUsed)
|
|
{
|
|
m_bHaveMapPath = true;
|
|
_tcscpy(m_szLaunchMapFile, m_szLauncherResources);
|
|
_tcscat(m_szLaunchMapFile, m_szDefMapFile);
|
|
hFind = FindFirstFile(m_szLaunchMapFile, &data);
|
|
if (INVALID_HANDLE_VALUE != hFind)
|
|
{
|
|
m_bHaveDefMapFile = true;
|
|
FindClose(hFind);
|
|
}
|
|
else
|
|
{
|
|
m_bHaveDefMapFile = false;
|
|
}
|
|
}
|
|
}
|
|
reg.Close();
|
|
}
|
|
// Need the TShoot.ocx resource path to verify that the networks exist.
|
|
if (ERROR_SUCCESS == reg.Open(HKEY_LOCAL_MACHINE, SZ_TSHOOT_ROOT))
|
|
{
|
|
dwBufSize = MAX_PATH;
|
|
TCHAR szDszResPath[MAX_PATH];
|
|
if (ERROR_SUCCESS == reg.QueryValue(szDszResPath, SZ_TSHOOT_RES, &dwBufSize))
|
|
{
|
|
if ('\\' != szDszResPath[_tcslen(szDszResPath) - 1])
|
|
_tcscat(szDszResPath, _T("\\"));
|
|
|
|
dwBufSize = MAX_PATH;
|
|
dwBytesUsed = ExpandEnvironmentStrings(szDszResPath, m_szDszResPath, dwBufSize); // The value returned by ExpandEnviromentStrings is larger than the required size.
|
|
if (0 == dwBytesUsed)
|
|
m_bHaveDszPath = false;
|
|
else
|
|
m_bHaveDszPath = true;
|
|
}
|
|
reg.Close();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// This initialization can happen more than once for the object.
|
|
// If we are going to use the same object to make a second request, there are things we
|
|
// want to clean up.
|
|
void CLaunch::InitRequest()
|
|
{
|
|
m_szAppName[0] = NULL;
|
|
m_szAppVersion[0] = NULL;
|
|
m_szAppProblem[0] = NULL;
|
|
m_stkStatus.RemoveAll();
|
|
m_Item.ReInit();
|
|
}
|
|
|
|
// >>> Why does this exist distinct from InitRequest()?
|
|
void CLaunch::ReInit()
|
|
{
|
|
InitRequest();
|
|
return;
|
|
}
|
|
|
|
// >>> What exactly is the use of this? What is the distinction from InitRequest()?
|
|
void CLaunch::Clear()
|
|
{
|
|
m_szAppName[0] = NULL;
|
|
m_szAppVersion[0] = NULL;
|
|
m_szAppProblem[0] = NULL;
|
|
m_stkStatus.RemoveAll();
|
|
m_Item.Clear();
|
|
return;
|
|
}
|
|
|
|
// Verify that a given troubleshooting belief network exists.
|
|
bool CLaunch::VerifyNetworkExists(LPCTSTR szNetwork)
|
|
{
|
|
bool bResult = true;
|
|
if (NULL == szNetwork || NULL == szNetwork[0])
|
|
{
|
|
// Null name, don't even bother with a lookup.
|
|
m_stkStatus.Push(TSL_E_NETWORK_NF);
|
|
bResult = false;
|
|
}
|
|
else
|
|
{
|
|
if (m_bHaveDszPath)
|
|
{
|
|
WIN32_FIND_DATA data;
|
|
HANDLE hFind;
|
|
TCHAR szDszFile[MAX_PATH];
|
|
|
|
_tcscpy(szDszFile, m_szDszResPath);
|
|
_tcscat(szDszFile, szNetwork);
|
|
_tcscat(szDszFile, _T(".ds?"));
|
|
|
|
hFind = FindFirstFile(szDszFile, &data);
|
|
if (INVALID_HANDLE_VALUE == hFind)
|
|
{
|
|
m_stkStatus.Push(TSL_E_NETWORK_NF);
|
|
bResult = false;
|
|
}
|
|
FindClose(hFind);
|
|
}
|
|
else
|
|
{
|
|
// we don't know what directory to look in.
|
|
m_stkStatus.Push(TSL_E_NETWORK_REG);
|
|
bResult = false;
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
// Allows explicit specification of the troubleshooting network (and, optionally,
|
|
// problem node) to launch to.
|
|
// This is an alternative to determining network/node via a mapping.
|
|
// INPUT szNetwork
|
|
// INPUT szProblem: null pointer of null string ==> no problem node
|
|
// any other value is symbolic name of problem node
|
|
bool CLaunch::SpecifyProblem(LPCTSTR szNetwork, LPCTSTR szProblem)
|
|
{
|
|
bool bResult = true;
|
|
if (!VerifyNetworkExists(szNetwork)) // Sets the network not found error.
|
|
{
|
|
bResult = false;
|
|
}
|
|
else
|
|
{
|
|
m_Item.SetNetwork(szNetwork);
|
|
|
|
// Set problem node, if any. OK if there is none.
|
|
if (NULL != szProblem && NULL != szProblem[0])
|
|
m_Item.SetProblem(szProblem);
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
// Allows explicit setting of a non-problem node.
|
|
// Obviously, node names only acquire meaning in the context of a belief network.
|
|
// INPUT szNode: symbolic node name
|
|
// INPUT szState: >>> not sure what is intended. The corresponding value in TSLaunch API is
|
|
// an integer state value. Is this the decimal representation of that value or what? JM
|
|
|
|
bool CLaunch::SetNode(LPCTSTR szNode, LPCTSTR szState)
|
|
{
|
|
bool bResult = true;
|
|
if (NULL != szNode && NULL != szState)
|
|
{
|
|
m_Item.SetNode(szNode, szState);
|
|
}
|
|
else
|
|
{
|
|
m_stkStatus.Push(TSL_E_NODE_EMP);
|
|
bResult = false;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
// Sets machine ID so that WBEM can sniff on a remote machine.
|
|
HRESULT CLaunch::MachineID(BSTR &bstrMachineID, DWORD *pdwResult)
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
if (!BSTRToTCHAR(m_Item.m_szMachineID, bstrMachineID, CItem::GUID_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
hRes = TSL_E_FAIL;
|
|
}
|
|
return hRes;
|
|
}
|
|
|
|
// Sets Device Instance ID so that WBEM can sniff correct device
|
|
HRESULT CLaunch::DeviceInstanceID(BSTR &bstrDeviceInstanceID, DWORD *pdwResult)
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
if (!BSTRToTCHAR(m_Item.m_szDeviceInstanceID, bstrDeviceInstanceID, CItem::GUID_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
hRes = TSL_E_FAIL;
|
|
}
|
|
return hRes;
|
|
}
|
|
|
|
void CLaunch::SetPreferOnline(short bPreferOnline)
|
|
{
|
|
// The next line's ugly, but correct. bPreferOnline is not necessarily a valid
|
|
// Boolean; we want to make sure we get a valid Boolean in m_bPreferOnline.
|
|
m_bPreferOnline = (0 != bPreferOnline);
|
|
return;
|
|
}
|
|
|
|
// CheckMapFile: Uses szAppName member to set szMapFile.
|
|
// First, check the registry for an application-specific map file. If we can't find one,
|
|
// check for a default map file. If that doesn't exist either, fail.
|
|
// INPUT szAppName
|
|
// OUTPUT szMapFile
|
|
bool CLaunch::CheckMapFile(TCHAR * szAppName, TCHAR szMapFile[MAX_PATH], DWORD *pdwResult)
|
|
{
|
|
bool bHaveMapFile = false;
|
|
|
|
if (NULL == szAppName || NULL == szAppName[0])
|
|
{
|
|
// Application name may not be null.
|
|
m_stkStatus.Push(TSL_ERROR_UNKNOWN_APP);
|
|
*pdwResult = TSL_ERROR_GENERAL;
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwBufSize;
|
|
CRegKey reg;
|
|
if (ERROR_SUCCESS == reg.Open(HKEY_LOCAL_MACHINE, SZ_LAUNCHER_APP_ROOT))
|
|
{
|
|
dwBufSize = MAX_PATH;
|
|
if (ERROR_SUCCESS == reg.Open(reg.m_hKey, szAppName))
|
|
{
|
|
if (ERROR_SUCCESS == reg.QueryValue(szMapFile, SZ_APPS_MAP_FILE, &dwBufSize))
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Does a default map file exist?
|
|
if (m_bHaveDefMapFile)
|
|
{
|
|
_tcscpy(szMapFile, m_szLaunchMapFile);
|
|
}
|
|
else
|
|
{ // Either the registry setting is missing or the file is not
|
|
// where the registry says it is.
|
|
if (m_bHaveMapPath) // Have the registry entry.
|
|
m_stkStatus.Push(TSL_E_MAPPING_DB_NF);
|
|
else
|
|
m_stkStatus.Push(TSL_E_MAPPING_DB_REG);
|
|
*pdwResult = TSL_ERROR_GENERAL;
|
|
}
|
|
return m_bHaveDefMapFile;
|
|
}
|
|
|
|
// Uses the mapping classes to map Caller() and DeviceID() information, then copies the
|
|
// CItem to global memory.
|
|
// >> Why is this called TestPut()?
|
|
// Returns false when the mapping fails.
|
|
bool CLaunch::TestPut()
|
|
{
|
|
extern CSMStateInfo g_StateInfo;
|
|
DWORD dwResult;
|
|
Map(&dwResult);
|
|
if (TSL_OK != dwResult)
|
|
return false;
|
|
g_StateInfo.TestPut(m_Item); // Copies m_Item to global memory.
|
|
return true;
|
|
}
|
|
|
|
// Perform any necessary mapping, then launch the Local Troubleshooter.
|
|
bool CLaunch::Go(DWORD dwTimeOut, DWORD *pdwResult)
|
|
{
|
|
DWORD dwRes;
|
|
bool bResult = true;
|
|
extern CSMStateInfo g_StateInfo;
|
|
TCHAR szContainerPathName[MAX_PATH]; szContainerPathName[0] = 0;
|
|
TCHAR szSniffScriptFile[MAX_PATH]; szSniffScriptFile[0] = 0;
|
|
TCHAR szSniffStandardFile[MAX_PATH]; szSniffStandardFile[0] = 0;
|
|
TCHAR szWebPage[MAX_PATH]; szWebPage[0] = 0;
|
|
TCHAR szDefaultNetwork[SYM_LEN]; szDefaultNetwork[0] = 0;
|
|
TCHAR *szCmd = NULL, *szNetwork = NULL;
|
|
|
|
if (TSL_OK == (dwRes = GetContainerPathName(szContainerPathName)))
|
|
{
|
|
m_Item.SetContainerPathName(szContainerPathName);
|
|
m_Item.SetSniffScriptFile(szSniffScriptFile);
|
|
}
|
|
else
|
|
{
|
|
m_stkStatus.Push(dwRes);
|
|
// if container is not found - no reason to continue
|
|
*pdwResult = TSL_ERROR_GENERAL;
|
|
return false;
|
|
}
|
|
|
|
if (!m_Item.NetworkSet())
|
|
{
|
|
if (Map(&dwRes) &&
|
|
TSL_OK == (dwRes = GetWebPage(szWebPage)) // get web page
|
|
)
|
|
{
|
|
m_Item.SetWebPage(szWebPage);
|
|
// network and problem are set by Map function
|
|
m_Item.SetLaunchRegime(launchMap);
|
|
}
|
|
else
|
|
{
|
|
m_stkStatus.Push(dwRes);
|
|
if (TSL_OK == (dwRes = GetDefaultURL(szWebPage))) // get "DEFAULT PAGE",
|
|
// actually a URL which might (for example)
|
|
// refernce a page compiled into a .CHM file
|
|
{
|
|
m_Item.SetWebPage(szWebPage);
|
|
m_Item.SetNetwork(NULL); // network are set to NULL in this case
|
|
m_Item.SetProblem(NULL); // problem are set to NULL in this case
|
|
m_Item.SetLaunchRegime(launchDefaultWebPage);
|
|
}
|
|
else
|
|
{
|
|
if (TSL_OK == (dwRes = GetDefaultNetwork(szDefaultNetwork)) && // get default network
|
|
TSL_OK == (dwRes = GetWebPage(szWebPage)) // get web page
|
|
)
|
|
{
|
|
m_Item.SetWebPage(szWebPage);
|
|
m_Item.SetNetwork(szDefaultNetwork);
|
|
m_Item.SetProblem(NULL); // problem is set to NULL in this case
|
|
m_Item.SetLaunchRegime(launchDefaultNetwork);
|
|
}
|
|
else
|
|
{
|
|
// complete failure
|
|
m_stkStatus.Push(dwRes);
|
|
*pdwResult = TSL_ERROR_GENERAL;
|
|
m_Item.SetLaunchRegime(launchIndefinite);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (TSL_OK == (dwRes = GetWebPage(szWebPage)))
|
|
{
|
|
m_Item.SetWebPage(szWebPage);
|
|
// network is known, problem can be either known(set) or unknown(not set)
|
|
m_Item.SetLaunchRegime(launchKnownNetwork);
|
|
}
|
|
else
|
|
{
|
|
// complete failure
|
|
m_stkStatus.Push(dwRes);
|
|
*pdwResult = TSL_ERROR_GENERAL;
|
|
m_Item.SetLaunchRegime(launchIndefinite);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// set sniff script and standard file
|
|
m_Item.GetNetwork(&szCmd, &szNetwork);
|
|
if (TSL_OK == (dwRes = GetSniffScriptFile(szSniffScriptFile, szNetwork[0] ? szNetwork : NULL)) &&
|
|
TSL_OK == (dwRes = GetSniffStandardFile(szSniffStandardFile))
|
|
)
|
|
{
|
|
m_Item.SetSniffScriptFile(szSniffScriptFile);
|
|
m_Item.SetSniffStandardFile(szSniffStandardFile);
|
|
}
|
|
else
|
|
{
|
|
// can not find script file path - failure
|
|
m_stkStatus.Push(dwRes);
|
|
*pdwResult = TSL_ERROR_GENERAL;
|
|
m_Item.SetLaunchRegime(launchIndefinite);
|
|
return false;
|
|
}
|
|
|
|
// parse warnings according to the launch regime
|
|
//
|
|
if (launchMap == m_Item.GetLaunchRegime() ||
|
|
launchKnownNetwork == m_Item.GetLaunchRegime()
|
|
)
|
|
{
|
|
if (!m_Item.ProblemSet())
|
|
{
|
|
m_stkStatus.Push(TSL_WARNING_NO_PROBLEM_NODE);
|
|
*pdwResult = TSL_WARNING_GENERAL;
|
|
}
|
|
}
|
|
|
|
// parse launches according to the launch regime
|
|
//
|
|
if (launchMap == m_Item.GetLaunchRegime() ||
|
|
launchDefaultNetwork == m_Item.GetLaunchRegime()
|
|
)
|
|
{
|
|
if (m_Item.NetworkSet())
|
|
{
|
|
|
|
#ifdef JDEBUG
|
|
HANDLE hDebugFile;
|
|
char* szStart = "START\n";
|
|
char* szEnd = "END\n";
|
|
DWORD dwBytesWritten;
|
|
|
|
hDebugFile = CreateFile(
|
|
_T("jdebug.txt"),
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
WriteFile(
|
|
hDebugFile,
|
|
szStart,
|
|
strlen(szStart),
|
|
&dwBytesWritten,
|
|
NULL);
|
|
|
|
TCHAR *sztCmd, *sztVal;
|
|
char sz[200], szCmd[100], szVal[100];
|
|
|
|
m_Item.GetNetwork(&sztCmd, &sztVal);
|
|
|
|
ToSBCS (szCmd, sztCmd, 100);
|
|
ToSBCS (szVal, sztVal, 100);
|
|
|
|
sprintf(sz, "%s %s\n", szCmd, szVal);
|
|
|
|
WriteFile(
|
|
hDebugFile,
|
|
sz,
|
|
strlen(sz),
|
|
&dwBytesWritten,
|
|
NULL);
|
|
|
|
if (m_Item.ProblemSet())
|
|
{
|
|
m_Item.GetProblem(&sztCmd, &sztVal);
|
|
|
|
ToSBCS (szCmd, sztCmd, 100);
|
|
ToSBCS (szVal, sztVal, 100);
|
|
|
|
sprintf(sz, "%s %s\n", szCmd, szVal);
|
|
|
|
WriteFile(
|
|
hDebugFile,
|
|
sz,
|
|
strlen(sz),
|
|
&dwBytesWritten,
|
|
NULL);
|
|
}
|
|
|
|
WriteFile(
|
|
hDebugFile,
|
|
szEnd,
|
|
strlen(szEnd),
|
|
&dwBytesWritten,
|
|
NULL);
|
|
CloseHandle(hDebugFile);
|
|
#endif
|
|
bResult = g_StateInfo.GoGo(dwTimeOut, m_Item, pdwResult);
|
|
}
|
|
else
|
|
{
|
|
*pdwResult = TSL_ERROR_GENERAL;
|
|
m_stkStatus.Push(TSL_ERROR_NO_NETWORK);
|
|
bResult = false;
|
|
}
|
|
}
|
|
|
|
if (launchKnownNetwork == m_Item.GetLaunchRegime() )
|
|
{
|
|
bResult = g_StateInfo.GoGo(dwTimeOut, m_Item, pdwResult);
|
|
}
|
|
|
|
if (launchDefaultWebPage == m_Item.GetLaunchRegime())
|
|
{
|
|
bResult = g_StateInfo.GoURL(m_Item, pdwResult);
|
|
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
HRESULT CLaunch::LaunchKnown(DWORD * pdwResult)
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
// Launch the shooter.
|
|
if (!Go(m_lLaunchWaitTimeOut, pdwResult))
|
|
hRes = TSL_E_FAIL;
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT CLaunch::Launch(BSTR bstrCallerName, BSTR bstrCallerVersion,
|
|
BSTR bstrAppProblem, short bLaunch, DWORD * pdwResult)
|
|
{
|
|
HRESULT hRes = S_OK;
|
|
Clear();
|
|
if (!BSTRToTCHAR(m_szAppName, bstrCallerName, SYM_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
return TSL_E_FAIL;
|
|
}
|
|
if (!BSTRToTCHAR(m_szAppVersion, bstrCallerVersion, SYM_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
return TSL_E_FAIL;
|
|
}
|
|
if (!BSTRToTCHAR(m_szAppProblem, bstrAppProblem, SYM_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
return TSL_E_FAIL;
|
|
}
|
|
if (bLaunch)
|
|
{
|
|
if (!Go(m_lLaunchWaitTimeOut, pdwResult))
|
|
hRes = TSL_E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
if (!Map(pdwResult))
|
|
hRes = TSL_E_FAIL;
|
|
}
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT CLaunch::LaunchDevice(BSTR bstrCallerName, BSTR bstrCallerVersion, BSTR bstrPNPDeviceID,
|
|
BSTR bstrDeviceClassGUID, BSTR bstrAppProblem, short bLaunch, DWORD * pdwResult)
|
|
{
|
|
HRESULT hRes;
|
|
Clear();
|
|
|
|
if (!BSTRToTCHAR(m_szAppName, bstrCallerName, SYM_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
return TSL_E_FAIL;
|
|
}
|
|
if (!BSTRToTCHAR(m_szAppVersion, bstrCallerVersion, SYM_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
return TSL_E_FAIL;
|
|
}
|
|
if (!BSTRToTCHAR(m_szAppProblem, bstrAppProblem, SYM_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
return TSL_E_FAIL;
|
|
}
|
|
if (!BSTRToTCHAR(m_Item.m_szPNPDeviceID, bstrPNPDeviceID, CItem::GUID_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
return TSL_E_FAIL;
|
|
}
|
|
if (!BSTRToTCHAR(m_Item.m_szGuidClass, bstrDeviceClassGUID, CItem::GUID_LEN))
|
|
{
|
|
*pdwResult = TSL_E_MEM_EXCESSIVE;
|
|
return TSL_E_FAIL;
|
|
}
|
|
if (m_Item.m_szGuidClass[0])
|
|
{
|
|
// Device Class GUID is non-null. Make sure it's a valid GUID.
|
|
GUID guidClass;
|
|
#ifdef _UNICODE
|
|
RPC_STATUS rpcstatus = UuidFromString(
|
|
m_Item.m_szGuidClass, &guidClass );
|
|
#else
|
|
RPC_STATUS rpcstatus = UuidFromString(
|
|
(unsigned char *) m_Item.m_szGuidClass, &guidClass );
|
|
#endif
|
|
if ( rpcstatus == RPC_S_INVALID_STRING_UUID)
|
|
{
|
|
m_stkStatus.Push(TSL_WARNING_ILLFORMED_CLASS_GUID);
|
|
}
|
|
}
|
|
|
|
if (bLaunch)
|
|
{
|
|
if (!Go(m_lLaunchWaitTimeOut, pdwResult))
|
|
hRes = TSL_E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
if (!Map(pdwResult))
|
|
hRes = TSL_E_FAIL;
|
|
}
|
|
return hRes;
|
|
}
|
|
|
|
DWORD CLaunch::GetStatus()
|
|
{
|
|
DWORD dwStatus = TSL_OK;
|
|
if (!m_stkStatus.Empty())
|
|
dwStatus = m_stkStatus.Pop();
|
|
return dwStatus;
|
|
}
|
|
|
|
// OUTPUT *szPathName = Name of application to launch to (either IE or HTML Help System)
|
|
// Returns:
|
|
// TSL_OK - success
|
|
// TSL_E_CONTAINER_REG - failure to find IE (Internet Explorer) in registry
|
|
// TSL_E_CONTAINER_NF - IE isn't where registry says to find it.
|
|
int CLaunch::GetContainerPathName(TCHAR szPathName[MAX_PATH])
|
|
{
|
|
DWORD dwPathNameLen = MAX_PATH;
|
|
int tslaHaveContainer = TSL_OK;
|
|
#ifndef _HH_CHM
|
|
// use IE instead of HTML Help System
|
|
if (!ReadRegSZ(HKEY_LOCAL_MACHINE,
|
|
SZ_CONTAINER_APP_KEY,
|
|
SZ_CONTAINER_APP_VALUE, szPathName, &dwPathNameLen))
|
|
{
|
|
tslaHaveContainer = TSL_E_CONTAINER_REG;
|
|
}
|
|
else
|
|
{ // Need to verify that the container exists.
|
|
WIN32_FIND_DATA data;
|
|
HANDLE hContainer = FindFirstFile(szPathName, &data);
|
|
if (INVALID_HANDLE_VALUE == hContainer)
|
|
tslaHaveContainer = TSL_E_CONTAINER_NF;
|
|
else
|
|
FindClose(hContainer);
|
|
}
|
|
#else
|
|
_tcscpy(szPathName, _T("hh.exe"));
|
|
#endif
|
|
return tslaHaveContainer;
|
|
}
|
|
|
|
// OUTPUT *szWebPage = Name of web page to launch to
|
|
// We always launch to the same web page. The information passed in m_Item ditinguishes
|
|
// what will actually show on the screen.
|
|
// Path is from registry. We concatenate on a backslash and SZ_WEB_PAGE (== "asklibrary.htm")
|
|
// Returns:
|
|
// TSL_OK - success
|
|
// TSL_E_WEB_PAGE_REG - failure to find web page for this purpose in registry
|
|
// TSL_E_MEM_EXCESSIVE - Web page name longer than we can handle
|
|
// TSL_E_WEB_PAGE_NF - Web page isn't where registry says to find it.
|
|
int CLaunch::GetWebPage(TCHAR szWebPage[MAX_PATH])
|
|
{
|
|
int tslaHavePage = TSL_OK;
|
|
DWORD dwWebPageLen = MAX_PATH;
|
|
if (!ReadRegSZ(HKEY_LOCAL_MACHINE,
|
|
SZ_LAUNCHER_ROOT,
|
|
SZ_GLOBAL_LAUNCHER_RES,
|
|
szWebPage,
|
|
&dwWebPageLen))
|
|
{
|
|
tslaHavePage = TSL_E_WEB_PAGE_REG;
|
|
}
|
|
else
|
|
{
|
|
int Len = _tcslen(szWebPage);
|
|
dwWebPageLen = Len + 1 + _tcslen(SZ_WEB_PAGE);
|
|
if (dwWebPageLen > MAX_PATH)
|
|
{
|
|
tslaHavePage = TSL_E_MEM_EXCESSIVE;
|
|
}
|
|
else
|
|
{
|
|
if (szWebPage[Len - 1] != '\\')
|
|
_tcscat(szWebPage, _T("\\"));
|
|
_tcscat(szWebPage, SZ_WEB_PAGE);
|
|
|
|
WIN32_FIND_DATA data;
|
|
HANDLE hWebPage = FindFirstFile(szWebPage, &data);
|
|
if (INVALID_HANDLE_VALUE == hWebPage)
|
|
tslaHavePage = TSL_E_WEB_PAGE_NF;
|
|
else
|
|
FindClose(hWebPage);
|
|
}
|
|
}
|
|
return tslaHavePage;
|
|
}
|
|
|
|
// OUTPUT *szSniffScriptFile = full path and file name either to "network"_sniff.htm file or null len string if file is not found
|
|
// TSL_OK - success
|
|
// TSL_E_SNIFF_SCRIPT_REG - failure to find file for this purpose in registry
|
|
int CLaunch::GetSniffScriptFile(TCHAR szSniffScriptFile[MAX_PATH], TCHAR* szNetwork)
|
|
{
|
|
int tslaHavePage = TSL_OK;
|
|
DWORD dwSniffScriptLen = MAX_PATH;
|
|
TCHAR szSniffScriptPath[MAX_PATH] = {0};
|
|
|
|
if (ReadRegSZ(HKEY_LOCAL_MACHINE,
|
|
SZ_TSHOOT_ROOT,
|
|
SZ_TSHOOT_RES,
|
|
szSniffScriptPath,
|
|
&dwSniffScriptLen))
|
|
{
|
|
int Len = _tcslen(szSniffScriptPath);
|
|
|
|
dwSniffScriptLen = Len + 1 + (szNetwork ? _tcslen(szNetwork) + _tcslen(SZ_SNIFF_SCRIPT_APPENDIX)
|
|
: 0);
|
|
|
|
if (dwSniffScriptLen > MAX_PATH)
|
|
{
|
|
tslaHavePage = TSL_E_MEM_EXCESSIVE;
|
|
}
|
|
else
|
|
{
|
|
if (szSniffScriptPath[Len - 1] != '\\')
|
|
_tcscat(szSniffScriptPath, _T("\\"));
|
|
|
|
if (szNetwork)
|
|
{
|
|
TCHAR tmp[MAX_PATH] = {0};
|
|
_tcscpy(tmp, szSniffScriptPath);
|
|
_tcscat(tmp, szNetwork);
|
|
_tcscat(tmp, SZ_SNIFF_SCRIPT_APPENDIX);
|
|
|
|
WIN32_FIND_DATA data;
|
|
HANDLE hSniffScript = FindFirstFile(tmp, &data);
|
|
|
|
if (INVALID_HANDLE_VALUE == hSniffScript)
|
|
{
|
|
szSniffScriptFile[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
_tcscpy(szSniffScriptFile, tmp);
|
|
FindClose(hSniffScript);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
szSniffScriptFile[0] = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tslaHavePage = TSL_E_SNIFF_SCRIPT_REG;
|
|
}
|
|
|
|
return tslaHavePage;
|
|
}
|
|
|
|
// OUTPUT *szSniffScriptFile = full path and file name of tssniffAsk.htm file no matter if it exists
|
|
// TSL_OK - success
|
|
// TSL_E_SNIFF_SCRIPT_REG - failure to find file for this purpose in registry
|
|
int CLaunch::GetSniffStandardFile(TCHAR szSniffStandardFile[MAX_PATH])
|
|
{
|
|
int tslaHavePage = TSL_OK;
|
|
DWORD dwSniffStandardLen = MAX_PATH;
|
|
TCHAR szSniffStandardPath[MAX_PATH] = {0};
|
|
|
|
if (ReadRegSZ(HKEY_LOCAL_MACHINE,
|
|
SZ_LAUNCHER_ROOT,
|
|
SZ_GLOBAL_LAUNCHER_RES,
|
|
szSniffStandardPath,
|
|
&dwSniffStandardLen))
|
|
{
|
|
int Len = _tcslen(szSniffStandardPath);
|
|
|
|
dwSniffStandardLen = Len + 1 + _tcslen(SZ_SNIFF_SCRIPT_NAME);
|
|
|
|
if (dwSniffStandardLen > MAX_PATH)
|
|
{
|
|
tslaHavePage = TSL_E_MEM_EXCESSIVE;
|
|
}
|
|
else
|
|
{
|
|
if (szSniffStandardPath[Len - 1] != '\\')
|
|
_tcscat(szSniffStandardPath, _T("\\"));
|
|
|
|
_tcscpy(szSniffStandardFile, szSniffStandardPath);
|
|
_tcscat(szSniffStandardFile, SZ_SNIFF_SCRIPT_NAME);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tslaHavePage = TSL_E_SNIFF_SCRIPT_REG;
|
|
}
|
|
|
|
return tslaHavePage;
|
|
}
|
|
|
|
// OUTPUT *szURL = URL to go to when mapping fails. We get this from registry.
|
|
// TSL_OK - success
|
|
// TSL_E_WEB_PAGE_REG - failure to find web page for this purpose in registry
|
|
int CLaunch::GetDefaultURL(TCHAR szURL[MAX_PATH])
|
|
{
|
|
int tslaHaveURL = TSL_OK;
|
|
DWORD dwURLLen = MAX_PATH;
|
|
if (!ReadRegSZ(HKEY_LOCAL_MACHINE,
|
|
SZ_LAUNCHER_ROOT,
|
|
SZ_DEFAULT_PAGE,
|
|
szURL,
|
|
&dwURLLen))
|
|
{
|
|
tslaHaveURL = TSL_E_WEB_PAGE_REG;
|
|
}
|
|
return tslaHaveURL;
|
|
}
|
|
|
|
// Returns TSL_OK and default network name in szDefaultNetwork
|
|
// if successful
|
|
int CLaunch::GetDefaultNetwork(TCHAR szDefaultNetwork[SYM_LEN])
|
|
{
|
|
DWORD dwLen = SYM_LEN;
|
|
|
|
if (ReadRegSZ(HKEY_LOCAL_MACHINE, SZ_LAUNCHER_ROOT, SZ_DEFAULT_NETWORK,
|
|
szDefaultNetwork, &dwLen))
|
|
if (VerifyNetworkExists(szDefaultNetwork))
|
|
|
|
return TSL_OK;
|
|
|
|
return TSL_E_NO_DEFAULT_NET;
|
|
}
|
|
|
|
bool CLaunch::Map(DWORD *pdwResult)
|
|
{
|
|
bool bOK = true;
|
|
TCHAR szMapFile[MAX_PATH];
|
|
TCHAR szNetwork[SYM_LEN]; szNetwork[0] = NULL;
|
|
TCHAR szTShootProblem[SYM_LEN]; szTShootProblem[0] = NULL;
|
|
|
|
bOK = CheckMapFile(m_szAppName, szMapFile, pdwResult);
|
|
|
|
// bOK false at this point means either the registry setting is missing or the file
|
|
// is not where the registry says it is. PdwResult has already been set in CheckMapFile.
|
|
|
|
if (bOK && _tcscmp(m_szMapFile, szMapFile))
|
|
{
|
|
// The mapping file we desire is _not_ already loaded
|
|
if (m_pMap)
|
|
{
|
|
// we were using a different mapping file. We have to get rid of it.
|
|
delete m_pMap;
|
|
}
|
|
// else we weren't using a mapping file yet.
|
|
|
|
m_pMap = new TSMapClient(szMapFile);
|
|
if (TSL_OK != m_pMap->GetStatus())
|
|
{
|
|
*pdwResult = m_pMap->GetStatus();
|
|
bOK = false;
|
|
}
|
|
else
|
|
{
|
|
// We've successfully init'd m_pMap on the basis of the new map file.
|
|
// Indicate that it's loaded.
|
|
_tcscpy(m_szMapFile, szMapFile);
|
|
}
|
|
}
|
|
|
|
if (bOK)
|
|
{
|
|
DWORD dwRes;
|
|
|
|
// Now perform mapping itself
|
|
//
|
|
dwRes = m_pMap->FromAppVerDevAndClassToTS(m_szAppName, m_szAppVersion,
|
|
m_Item.m_szPNPDeviceID, m_Item.m_szGuidClass, m_szAppProblem,
|
|
szNetwork, szTShootProblem);
|
|
|
|
// As documented for TSMapRuntimeAbstract::FromAppVerDevAndClassToTS(), there are two
|
|
// return values here which require that we check for further status details: TSL_OK
|
|
// (which means we found a mapping, but doesn't rule out warnings) and
|
|
// TSL_ERROR_NO_NETWORK (which means we didn't find a mapping, and is typically
|
|
// accompanied by further clarifications).
|
|
if (TSL_OK == dwRes || TSL_ERROR_NO_NETWORK == dwRes)
|
|
{
|
|
DWORD dwStatus;
|
|
while (0 != (dwStatus = m_pMap->MoreStatus()))
|
|
m_stkStatus.Push(dwStatus);
|
|
}
|
|
|
|
if (TSL_OK != dwRes)
|
|
m_stkStatus.Push(dwRes); // save the precise error status
|
|
|
|
if (TSLIsError(dwRes) )
|
|
bOK = false;
|
|
|
|
if (bOK)
|
|
{
|
|
// We have a network name.
|
|
bOK = VerifyNetworkExists(szNetwork);
|
|
}
|
|
|
|
if (bOK)
|
|
{
|
|
// We have a network name and we've verified that the network exists.
|
|
// Set the item's network and tshoot problem.
|
|
m_Item.SetNetwork(szNetwork);
|
|
m_Item.SetProblem(szTShootProblem);
|
|
}
|
|
else
|
|
*pdwResult = TSL_ERROR_GENERAL;
|
|
}
|
|
|
|
return bOK;
|
|
}
|