Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

847 lines
16 KiB

//
// MODULE: APGTSDTG.CPP
//
// PURPOSE: Wrapper for inference api
//
// PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
//
// COMPANY: Saltmine Creative, Inc. (206)-633-4743 [email protected]
//
// AUTHOR: Roman Mach
//
// ORIGINAL DATE: 8-2-96
//
// NOTES:
// 1. Based on Print Troubleshooter DLL
//
// Version Date By Comments
//--------------------------------------------------------------------
// V0.1 - RM Original
// V0.2 6/4/97 RWM Local Version for Memphis
// V0.3 04/09/98 JM/OK+ Local Version for NT5
//
//#include "windows.h"
#include "stdafx.h"
#include "time.h"
#include "apgts.h"
#include "ErrorEnums.h"
#include "bnts.h"
#include "BackupInfo.h"
#include "cachegen.h"
#include "apgtsinf.h"
#include "apgtscmd.h"
#include "apgtshtx.h"
#include "apgtscls.h"
#include <string.h>
#include <memory.h>
#include "CabUnCompress.h"
#include "crc.h"
#include "sniff.h"
#include "chmread.h"
BCache::BCache(TCHAR *binfile, TCHAR *tagstr, TCHAR *szResourcePath, const CString& strFile)
: GTSAPI(binfile, tagstr, szResourcePath),
CSniffedNodeContainer(),
m_NodeState(30),
m_strFile(strFile)
{
SetBNTS(this);
m_bNeedModel = TRUE; // TRUE -> Need to read the model before querying the bnts library.
m_bModelRead = FALSE;
m_bDeleteModelFile = FALSE;
m_strModelFile = _T("");
m_CurNode = 0;
m_pHttpQuery = NULL;
m_strResult = _T("");
m_NodeState.InitHashTable(47);
m_bReverse = false;
m_bRunWithKnownProblem = false;
return;
}
BCache::~BCache()
{
m_NodeState.RemoveAll();
if (m_bDeleteModelFile)
{
DeleteFile((LPCTSTR) m_strModelFile);
m_bDeleteModelFile = FALSE;
}
return;
}
//
//
GTSAPI::GTSAPI(TCHAR *binfile, TCHAR *tagstr, TCHAR *szResourcePath) :
m_CacheGen(TRUE, NULL, NULL)
{
// InitializeCriticalSection( &m_csAPI );
m_cnid = 0;
m_dwErr = 0;
m_pchHtml = NULL;
m_currid = 0;
m_pCache = NULL;
_tcscpy(m_binfile,binfile);// full path
_tcscpy(m_tagstr,tagstr);
_tcscpy(m_szResourcePath,szResourcePath);
}
//
//
GTSAPI::~GTSAPI()
{
Destroy();
}
void WideToMB(const WCHAR *szIn, CHAR *szOut)
{
VERIFY(WideCharToMultiByte(CP_ACP,
NULL,
szIn,
-1,
szOut,
MAXBUF,
NULL, NULL));
return;
}
#ifdef _UNICODE
// Temporary BNTS wrappers for unicode build with non unicode bnts.dll
BOOL GTSAPI::BMultiByteReadModel(LPCTSTR szcFn, LPCSTR szFnError)
{
CHAR szFn[MAXBUF];
WideToMB(szcFn, szFn);
return BNTS::BReadModel(szFn, szFnError);
}
BOOL GTSAPI::BMultiByteNodePropItemStr(LPCTSTR szcPropType, int index)
{
CHAR szPropType[MAXBUF];
WideToMB(szcPropType, szPropType);
return BNTS::BNodePropItemStr(szPropType, index);
}
BOOL GTSAPI::BMultiByteNetPropItemStr(LPCTSTR szcPropType, int index)
{
CHAR szPropType[MAXBUF];
WideToMB(szcPropType, szPropType);
return BNTS::BNetPropItemStr(szPropType, index);
}
const WCHAR * GTSAPI::SzcMultiByteResult()
{
int len = strlen(BNTS::SzcResult());
int size = MultiByteToWideChar(CP_ACP,
NULL,
BNTS::SzcResult(),
len,
NULL,
0);
MultiByteToWideChar(CP_ACP,
NULL,
BNTS::SzcResult(),
len + 1,
m_strResult.GetBufferSetLength(size),
size);
m_strResult.ReleaseBuffer();
return (LPCTSTR) m_strResult;
}
int GTSAPI::IMultiByteNode(LPCTSTR szSymName)
{
CHAR szMBSymName[MAXBUF];
WideToMB(szSymName, szMBSymName);
return BNTS::INode(szMBSymName);
}
#endif // _UNICODE
void BCache::ReadTheDscModel(int From)
{
if (m_bNeedModel)
{
if (!BReadModel((LPCTSTR) m_strModelFile
#ifdef _DEBUG
, "BNTSError.log"
#endif
))
ReportError((DLSTATTYPES) From);
// Add the nodes that are already instantiated.
if (m_pHttpQuery)
m_pHttpQuery->AddNodes(this);
m_bNeedModel = FALSE;
if (m_bDeleteModelFile)
{
DeleteFile((LPCTSTR) m_strModelFile);
m_bDeleteModelFile = FALSE;
}
}
}
VOID BCache::AddToCache(CString &strCacheFile, const CString& strCacheFileWithinCHM)
{
if (m_CacheGen.ReadCacheFileHeader(strCacheFile, strCacheFileWithinCHM))
{
BOOL bErr;
ASSERT(m_pCache);
while (m_CacheGen.GetNextCacheEntryFromFile(bErr, m_pCache))
;
if (bErr)
{
delete m_pCache;
m_pCache = new CBNCache();
TRACE(_T("Errors occured while reading the cache file.\n"));
ReadTheDscModel(TSERR_ENGINE_BNTS_READ_NCAB);
}
}
return;
}
DWORD BCache::ReadModel()
{
BOOL bDelete = FALSE;
// this should be fixed eventually to not require a string compare
// but maybe a flag check that gets passed in
CString sFilename = m_binfile;
CString strCacheFile;
CString strCacheFileWithinCHM;
if (m_strFile.GetLength())
{
// form Cache file path here assuming it is NOT in chm file
strCacheFile = m_binfile;
strCacheFileWithinCHM = m_strFile.Left(m_strFile.GetLength() - 4);
strCacheFileWithinCHM += SZ_CACHE_NAME;
}
else
{
strCacheFile = sFilename.Left(sFilename.GetLength() - 4);
strCacheFile += SZ_CACHE_NAME;
}
if (m_strFile.GetLength() || !sFilename.Right(4).CompareNoCase(DSC_COMPRESSED))
{
CCabUnCompress cab;
CString strDirBuf;
if (!GetTempPath( MAX_PATH , strDirBuf.GetBufferSetLength(MAX_PATH + 1)))
{
strDirBuf.ReleaseBuffer();
strDirBuf = m_szResourcePath;
}
else
{
strDirBuf.ReleaseBuffer();
}
if (!cab.ExtractCab(sFilename, strDirBuf, m_strFile))
{
if (NOT_A_CAB == cab.m_nError)
{ // The file may be uncompressed already.
bDelete = FALSE;
}
else
{
ReportError(TSERR_ENGINE_EXTRACT);
}
}
else
{ // Normal cab file expanded successfully.
sFilename = strDirBuf;
sFilename += cab.GetLastFile();
DWORD dwAttribs = GetFileAttributes((LPCTSTR) sFilename);
dwAttribs = dwAttribs & ~FILE_ATTRIBUTE_READONLY;
SetFileAttributes((LPCTSTR) sFilename, dwAttribs);
bDelete = TRUE;
}
}
/*
if (!BReadModel(sFilename
#ifdef _DEBUG
, "BNTSError.log"
#endif
))
ReportError(TSERR_ENGINE);
*/
m_strModelFile = sFilename;
m_bDeleteModelFile = bDelete;
// Compare the crc value in the cache file with the crc of the dsc file.
// If they match, fill the cache.
CCRC crc;
try
{
if (crc.Decode(sFilename, strCacheFile, strCacheFileWithinCHM))
AddToCache(strCacheFile, strCacheFileWithinCHM);
else
ReadTheDscModel(TSERR_ENGINE_BNTS_READ_CACH);
}
catch(CGenException *p)
{
delete p;
ReadTheDscModel(TSERR_ENGINE_BNTS_READ_GEN);
}
// if (bDelete)
// DeleteFile(sFilename);
m_probask = idhFirst + CNode();
m_bModelRead = TRUE;
return m_dwErr;
}
// Number of nodes whose states were set at program startup by TSLaunchServ.
UINT BCache::StatesFromServ()
{
return m_pHttpQuery ? m_pHttpQuery->StatesFromServ() : 0;
}
// Number of nodes whose states are now set
UINT BCache::StatesNowSet()
{
return (UINT)m_NodeState.GetCount();
}
//
//
DWORD BCache::Initialize(/*CWordList *pWXList*/)
{
if (NULL != m_pCache)
delete m_pCache;
m_pCache = new CBNCache();
if (!m_pCache)
m_dwErr = EV_GTS_ERROR_IDX_ALLOC_CACHE;
ResetNodes();
if (!BValidNet())
ReadModel();
return m_dwErr;
}
// override the default function
//
// look for possible returns in the header file
//
int BCache::GTSGetRecommendations(CNID& cnid, NID rgnid[], bool bSniffed)
{
BN_CACHE_ITEM SetupItem;
SetupItem.uNodeCount = m_cnid;
SetupItem.uName = m_rgnid;
SetupItem.uValue = m_rgist;
int state = SNIFF_INVALID_STATE;
int label = SNIFF_INVALID_NODE_LABEL;
//AfxDebugBreak();
// set initial non-sniffed value in array of sniffed states
if (!bSniffed && !IsReverse())
m_rgsniff[m_cnid-1] = 0;
// flush array of sniffed nodes recently traversed
if (!bSniffed)
m_arrNidLastSniffed.RemoveAll();
if (m_pCache->FindCacheItem(&SetupItem, cnid, rgnid))
{
if (GetState(*rgnid, &state)) // sniffer has this information and can answer what state this node has
{
if (NodeSet(*rgnid, state, false)) // set sniffed node current and set its state
{
SetAdditionalDataOnNodeSet(*rgnid);
return GTSGetRecommendations(cnid, rgnid, true); // recursive call - hope BNTS will not recommend a node which is set
}
}
else
{
return RECOMMEND_SUCCESS;
}
}
if (m_bNeedModel)
{
ReadTheDscModel(TSERR_ENGINE_BNTS_REC);
}
if (BGetRecommendations())
{
cnid = CInt();
if (cnid > 0)
{
const int *pInt = RgInt();
memcpy(rgnid, pInt, cnid * sizeof(pInt[0]));
SetupItem.uNodeCount = m_cnid;
SetupItem.uName = m_rgnid;
SetupItem.uValue = m_rgist;
SetupItem.uRecCount = cnid;
SetupItem.uRec = rgnid;
m_pCache->AddCacheItem(&SetupItem);
if (GetState(*rgnid, &state)) // sniffer has this information and can answer what state this node has
{
if (NodeSet(*rgnid, state, false)) // set sniffed node current and set its state
{
SetAdditionalDataOnNodeSet(*rgnid);
return GTSGetRecommendations(cnid, rgnid, true); // recursive call - hope BNTS will not recommend a node which is set
}
}
return RECOMMEND_SUCCESS;
}
else
{
rgnid[0] = nidService;
cnid = 1;
return RECOMMEND_NO_MORE_DATA;
}
}
else
{
// the last node was sniffed and its state was set
// after that we received FALSE from BGetRecommendation;
// we unset this node (in order to be able to use BGetRecommendation later on);
// we return value indicating that BNTS cannot give us any recommendations
NodeSet(m_rgnid[m_cnid-1], -1, false);
return RECOMMEND_NO_MORE_DATA;
}
return RECOMMEND_FAIL;
}
void BCache::SetAdditionalDataOnNodeSet(NID nid)
{
m_rgsniff[m_cnid-1] = 1;
m_arrNidLastSniffed.Add(nid);
}
BOOL InArray(UINT num, UINT aNums[], UINT max)
{
UINT x = max;
BOOL bRes = FALSE;
for (UINT y = 0; y < x; y++)
{
if (aNums[y] == num)
{
bRes = TRUE;
break;
}
}
return bRes;
}
// RemoveRecommendations is called for nodes whos' state is less than 100.
void BCache::RemoveRecommendation(int Nid)
{
VERIFY(BNodeSetCurrent(Nid));
BNodeSet(-1, false);
if (m_cnid)
m_cnid--;
return;
}
//
//
UINT GTSAPI::GetNodeList(NID **pNid, IST **pIst)
{
*pNid = m_rgnid;
*pIst = m_rgist;
return m_cnid;
}
BOOL GTSAPI::BNodeSetCurrent(int node)
{
return BNTS::BNodeSetCurrent(node);
}
//
//
BOOL BCache::NodeSet(NID nid, IST ist, bool bPrevious)
{
BOOL bRes = FALSE;
// shouldn't happen...but to be safe
if (m_cnid >= MAX_NID)
return FALSE;
m_rgnid[m_cnid] = nid;
m_rgist[m_cnid] = ist;
if (false == bPrevious)
{
VERIFY(BNodeSetCurrent(nid));
bRes = BNodeSet(ist, false);
if (bRes && // bnts worked successfully
-1 == GetIndexNodeInCache(nid) // this nid is not present in the cache
)
m_cnid++;
}
else
{
bRes = TRUE;
}
return bRes;
}
//
//
int BCache::GetIndexNodeInCache(NID nid)
{
for (unsigned int i = 0; i < m_cnid; i++)
if (m_rgnid[i] == nid)
return i;
return -1;
}
//
//
VOID BCache::ResetNodes()
{
for (UINT inid = 0; inid < m_cnid; inid++)
{
VERIFY(BNodeSetCurrent(m_rgnid[inid]));
BNodeSet(-1, false); // Nil value
}
m_cnid = 0;
}
//
//
DWORD GTSAPI::GetStatus()
{
return m_dwErr;
}
//
//
VOID GTSAPI::Destroy()
{
if (m_pchHtml) {
delete [] m_pchHtml;
m_pchHtml = NULL;
}
/*
if (m_pWNList) {
if (!m_dwErr)
m_dwErr = m_pWNList->GetStatus();
delete m_pWNList;
m_pWNList = NULL;
}
*/
if (m_pCache) {
if (!m_dwErr)
m_dwErr = m_pCache->GetStatus();
delete m_pCache;
m_pCache = NULL;
}
}
//
//
UINT GTSAPI::GetProblemArray(IDH **idh)
{
*idh = m_idstore;
return m_currid;
}
//
//
IDH GTSAPI::GetProblemAsk()
{
return m_probask;
}
void GTSAPI::AddValue(int value)
{
ASSERT(m_currid < MAXPROBID);
m_idstore[m_currid++] = value;
return;
}
BOOL BCache::CheckNode(int Node)
{
BOOL bCached = m_CacheGen.IsNodePresent(Node);
if (!bCached && m_bNeedModel)
{
ReadTheDscModel(TSERR_ENGINE_BNTS_CHECK);
}
return bCached;
}
//-------------------------------------------------------------
// BNTS Overrides to replace the dsc file with our cache.
// Need to override everything but BReadModel and BGetRecommendations.
int BCache::CNode()
{
int cNodes;
if (FALSE == m_bNeedModel)
cNodes = GTSAPI::CNode();
else
cNodes = m_CacheGen.GetNodeCount();
return cNodes;
}
BOOL BCache::BImpossible()
{
BOOL bImpossible = FALSE;
if (FALSE == m_bNeedModel)
bImpossible = GTSAPI::BImpossible();
return bImpossible;
}
BOOL BCache::BNetPropItemStr(LPCTSTR szPropType, int index)
{
BOOL bGoodIndex = FALSE;
char sznPropType[MAX_SYM_NAME_BUF_LEN];
int nPropLen = MAX_SYM_NAME_BUF_LEN;
if (!GTSCacheGenerator::TcharToChar(sznPropType, szPropType, nPropLen))
return FALSE;
if (CheckNode(m_CurNode))
{
bGoodIndex = m_CacheGen.FindNetworkProperty(sznPropType, m_strResult, index);
if (!bGoodIndex && !m_bNeedModel)
{
bGoodIndex = GTSAPI::BNetPropItemStr(szPropType, index);
m_strResult = GTSAPI::SzcResult();
}
}
else
{
bGoodIndex = GTSAPI::BNetPropItemStr(szPropType, index);
m_strResult = GTSAPI::SzcResult();
}
return bGoodIndex;
}
BOOL BCache::BNodeSetCurrent(int node)
{
BOOL bNodeSet = TRUE;
if (CheckNode(node) && TRUE == m_bNeedModel)
{
m_CurNode = node;
}
else
{
bNodeSet = GTSAPI::BNodeSetCurrent(node);
m_CurNode = node;
}
return bNodeSet;
}
int BCache::INode(LPCTSTR szNodeSymName)
{
UINT index = 0;
if (FALSE == m_bNeedModel)
index = GTSAPI::INode(szNodeSymName);
else
if (!m_CacheGen.GetNodeIDFromSymName(szNodeSymName, index))
{ // Have to have BNTS load the network and the the symbolic name.
ReadTheDscModel(TSERR_ENGINE_CACHE_LOW);
index = GTSAPI::INode(szNodeSymName);
}
return (signed int) index;
}
ESTDLBL BCache::ELblNode()
{
UINT NodeLable;
ESTDLBL Lable;
if (FALSE == m_bNeedModel)
{
Lable = GTSAPI::ELblNode();
}
else
{
VERIFY(m_CacheGen.GetLabelOfNode(m_CurNode, NodeLable));
Lable = (ESTDLBL) NodeLable;
}
return Lable;
}
int BCache::INodeCst()
{
int cStates = 2;
return cStates;
}
BOOL GTSAPI::BNodeSet(int state, bool bset)
{
return BNTS::BNodeSet(state, bset);
}
BOOL BCache::BNodeSet(int istate, bool bSet)
{
BOOL bNodeWasSet = TRUE;
if (FALSE == m_bNeedModel)
bNodeWasSet = GTSAPI::BNodeSet(istate, bSet);
if (bNodeWasSet)
{
if (-1 != istate)
m_NodeState.SetAt(m_CurNode, istate);
else
m_NodeState.RemoveKey(m_CurNode);
}
return bNodeWasSet;
}
int BCache::INodeState()
{ // This is ok. See BNodeSet.
int state;
if (!m_NodeState.Lookup(m_CurNode, state))
state = 0;
return state;
}
void BCache::NodeStateName(int istate)
{
if (FALSE == m_bNeedModel)
{
GTSAPI::NodeStateName(istate);
m_strResult = GTSAPI::SzcResult();
}
else
{
BOOL bFound;
switch(istate)
{
case 0:
bFound = m_CacheGen.FindNodeProperty(m_CurNode, G_S0_NAME, m_strResult, 0);
break;
case 1:
bFound = m_CacheGen.FindNodeProperty(m_CurNode, G_S1_NAME, m_strResult, 0);
break;
default:
bFound = FALSE;
}
if (!bFound)
{
ASSERT(FALSE);
m_strResult = _T("");
}
}
return;
}
void BCache::NodeSymName()
{
if (FALSE == m_bNeedModel)
{
GTSAPI::NodeSymName();
m_strResult = GTSAPI::SzcResult();
}
else if (CheckNode(m_CurNode))
{
VERIFY(m_CacheGen.FindNodeProperty(m_CurNode, G_SYMBOLIC_NAME, m_strResult, 0));
}
return;
}
void BCache::NodeFullName()
{
if (FALSE == m_bNeedModel)
{
GTSAPI::NodeFullName();
m_strResult = GTSAPI::SzcResult();
}
else
{
VERIFY(m_CacheGen.FindNodeProperty(m_CurNode, G_FULL_NAME, m_strResult, 0));
}
return;
}
BOOL BCache::BNodePropItemStr(LPCTSTR szPropType, int index)
{
BOOL bGoodIndex = FALSE;
char sznPropType[MAX_SYM_NAME_BUF_LEN];
int nPropTypeLen = MAX_SYM_NAME_BUF_LEN;
if (!GTSCacheGenerator::TcharToChar(sznPropType, szPropType, nPropTypeLen))
return FALSE;
if (FALSE == m_bNeedModel)
{
bGoodIndex = GTSAPI::BNodePropItemStr(szPropType, index);
m_strResult = GTSAPI::SzcResult();
}
else
{
bGoodIndex = m_CacheGen.FindNodeProperty(m_CurNode, sznPropType, m_strResult, index);
}
return bGoodIndex;
}
bool BCache::BValidNet()
{
bool bValidNet;
if (FALSE == m_bModelRead) // Set to true in BCache::ReadModel.
bValidNet = false; // Causes the readmodel function to be called.
else if (FALSE == m_bNeedModel)
bValidNet = GTSAPI::BValidNet();
else
bValidNet = true;
return bValidNet;
}
LPCTSTR BCache::SzcResult() const
{
return (LPCTSTR) m_strResult;
}
const CArray<int, int>& BCache::GetArrLastSniffed()
{
return m_arrNidLastSniffed;
}
int BCache::GetCountRecommendedNodes()
{
return m_cnid;
}
int BCache::GetCountSniffedRecommendedNodes()
{
for (unsigned int i = 0, j = 0; i < m_cnid; i++)
if (m_rgsniff[i] == 1)
j++;
return j;
}
bool BCache::IsReverse()
{
return m_bReverse;
}
void BCache::SetReverse(bool reverse)
{
m_bReverse = reverse;
}
void BCache::SetRunWithKnownProblem(bool yes)
{
m_bRunWithKnownProblem = yes;
}
bool BCache::IsRunWithKnownProblem()
{
return m_bRunWithKnownProblem;
}