windows-nt/Source/XPSP1/NT/enduser/troubleshoot/control/apgtsqry.cpp
2020-09-26 16:20:57 +08:00

672 lines
15 KiB
C++

//
// MODULE: APGTSQRY.CPP
//
// PURPOSE: Implementation file for PTS Query Parser
//
// PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
//
//
// 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 "bnts.h"
#include "BackupInfo.h"
#include "cachegen.h"
#include "apgtsinf.h"
#include "apgtscmd.h"
#include "apgtshtx.h"
#include "apgtscls.h"
#include "ErrorEnums.h"
#include "BasicException.h"
#include "HttpQueryException.h"
#include "Functions.h"
#include "BackupInfo.h"
#include <string.h>
#include <stdlib.h>
#include "LaunchServ.h"
//
//
CHttpQuery::CHttpQuery()
{
m_pvarCmds = NULL;
m_pvarVals = NULL;
m_strCmd1 = _T("");
m_strVal1 = _T("");
m_CurrentUse = 0;
m_Size = 0;
m_bReverseStack = false;
m_nStatesFromServ = 0;
}
//
//
CHttpQuery::~CHttpQuery()
{
}
void CHttpQuery::ThrowBadParams(CString &str)
{
CHttpQueryException *pExc = new CHttpQueryException;
#ifndef __DEBUG_HTTPQUERY_
pExc->m_strError = _T("Script Error");
#else
pExc->m_strError = str;
#endif
throw pExc;
return;
}
void CHttpQuery::Initialize(const VARIANT FAR& varCmds, const VARIANT FAR& varVals, short size)
{
#ifdef __DEBUG_HTTPQUERY_
AfxMessageBox(_T("Cmd Variant Types:\n\n") + DecodeVariantTypes(varCmds.vt), MB_ICONINFORMATION);
AfxMessageBox(_T("Value Variant Types:\n\n") + DecodeVariantTypes(varVals.vt), MB_ICONINFORMATION);
#endif
const VARIANT FAR *pVarCmds;
const VARIANT FAR *pVarVals;
if (VT_BYREF == (VT_BYREF & varCmds.vt) &&
VT_VARIANT == (VT_VARIANT & varCmds.vt))
{
if (VT_ARRAY == (VT_ARRAY & varCmds.vt))
pVarCmds = &varCmds;
else
pVarCmds = varCmds.pvarVal;
}
else
{
pVarCmds = NULL;
CString str = _T("Cmd parameters from VB were not a variant or not by ref.");
ASSERT(FALSE);
TRACE(_T("%s\n"), str);
ThrowBadParams(str);
}
if (VT_BYREF == (VT_BYREF & varVals.vt) &&
VT_VARIANT == (VT_VARIANT & varVals.vt))
{
if (VT_ARRAY == (VT_ARRAY & varVals.vt))
pVarVals = &varVals;
else
pVarVals = varVals.pvarVal;
}
else
{
pVarVals = NULL;
CString str = _T("Cmd parameters from VB were not a variant or not by ref.");
ASSERT(FALSE);
TRACE(_T("%s\n"), str);
ThrowBadParams(str);
}
if (VT_BYREF != (VT_BYREF & pVarCmds->vt) ||
VT_ARRAY != (VT_ARRAY & pVarCmds->vt) ||
VT_VARIANT != (0xFFF & pVarCmds->vt))
{
CString str = _T("Wrong Cmd parameters passed from VB.");
ASSERT(FALSE);
TRACE(_T("%s\n"), str);
ThrowBadParams(str);
}
if (VT_BYREF != (VT_BYREF & pVarVals->vt) ||
VT_ARRAY != (VT_ARRAY & pVarVals->vt) ||
VT_VARIANT != (0xFFF & pVarVals->vt))
{
CString str = _T("Wrong Cmd parameters passed from VB.");
ASSERT(FALSE);
TRACE(_T("%s\n"), str);
ThrowBadParams(str);
}
#ifdef __DEBUG_HTTPQUERY_
AfxMessageBox(_T("Cmd Variant Types:\n\n") + DecodeVariantTypes(pVarCmds->vt), MB_ICONINFORMATION);
AfxMessageBox(_T("Value Variant Types:\n\n") + DecodeVariantTypes(pVarVals->vt), MB_ICONINFORMATION);
#endif
SAFEARRAY *pArrCmds = *(pVarCmds->pparray);
SAFEARRAY *pArrVals = *(pVarVals->pparray);
#ifdef __DEBUG_HTTPQUERY_
CString strSafe;
strSafe.Format("Cmd Safe Array\n\nDim: %d\nfeatures:\n%s\nSize of the Elements: %ld",
pArrCmds->cDims, (LPCTSTR) DecodeSafeArray(pArrCmds->fFeatures),
pArrCmds->cbElements);
AfxMessageBox(strSafe, MB_ICONINFORMATION);
strSafe.Format("Val Safe Array\n\nDim: %d\nfeatures:\n%s\nSize of the Elements: %ld",
pArrVals->cDims, (LPCTSTR) DecodeSafeArray(pArrVals->fFeatures),
pArrVals->cbElements);
AfxMessageBox(strSafe, MB_ICONINFORMATION);
#endif
if (0 != pArrCmds->rgsabound[0].lLbound || 0 != pArrVals->rgsabound[0].lLbound)
{
CString str = _T("Wrong Cmd parameters passed from VB. Lower bounds are wrong.");
ASSERT(FALSE);
TRACE(_T("%s\n"), str);
ThrowBadParams(str);
}
if (pArrCmds->rgsabound[0].cElements != pArrVals->rgsabound[0].cElements)
{
CString str = _T("Wrong Cmd parameters passed from VB. Cmds upperbound != Vals upperbound.");
ASSERT(FALSE);
TRACE(_T("%s\n"), str);
ThrowBadParams(str);
}
m_Size = size;
#ifdef __DEBUG_HTTPQUERY_
CString str;
str.Format("Size: %d", m_Size);
AfxMessageBox(str, MB_ICONINFORMATION);
#endif
m_pvarCmds = (VARIANT *) pArrCmds->pvData;
m_pvarVals = (VARIANT *) pArrVals->pvData;
if (0 != m_Size)
{
if (m_pvarCmds->vt != VT_BSTR || m_pvarVals->vt != VT_BSTR)
{
CString str;
str.Format(_T("Wrong Cmd parameters passed from VB. Array of unexpected type.\n\n")
_T("Cmd Type: %s\nVal Type: %s"),
(LPCTSTR) DecodeVariantTypes(m_pvarCmds->vt),
(LPCTSTR) DecodeVariantTypes(m_pvarVals->vt));
ASSERT(FALSE);
TRACE(_T("%s\n"), str);
ThrowBadParams(str);
}
}
CString strC = m_pvarCmds[0].bstrVal;
CString strD = m_pvarVals[0].bstrVal;
if (strC != m_strCmd1 || strD != m_strVal1)
m_State.RemoveAll();
m_strCmd1 = strC;
m_strVal1 = strD;
return;
}
BOOL CHttpQuery::StrIsDigit(LPCTSTR pSz)
{
BOOL bRet = TRUE;
while (*pSz)
{
if (!_istdigit(*pSz))
{
bRet = FALSE;
break;
}
pSz = _tcsinc(pSz);
}
return bRet;
}
void CHttpQuery::FinishInit(BCache *pApi, const VARIANT FAR& varCmds, const VARIANT FAR& varVals)
{
ASSERT(pApi);
ASSERT(m_Size > 0);
CNode node;
CString str;
if (!pApi)
return;
if (!pApi->BValidNet())
pApi->ReadModel();
m_bReverseStack = false;
for (int x = 1; x < m_Size; x++)
{
// Read the command.
str = m_pvarCmds[x].bstrVal;
if (StrIsDigit((LPCTSTR) str))
node.cmd = _ttoi(str);
else if (0 == _tcscmp(CHOOSE_TS_PROBLEM_NODE, (LPCTSTR) str))
node.cmd = pApi->CNode() + idhFirst;
else if (0 == _tcscmp(TRY_TS_AT_MICROSOFT_SZ, (LPCTSTR) str))
node.cmd = TRY_TS_AT_MICROSOFT_ID;
else
{
NID nid = pApi->INode((LPCTSTR) str);
if (nid == -1)
{
// Invalid node name. This also throws suspicion on anything further
// down the line. Just break out of the loop.
break;
}
node.cmd = nid + idhFirst;
}
// Read the value.
str = m_pvarVals[x].bstrVal;
if (StrIsDigit((LPCTSTR) str))
node.val = _ttoi(str);
else
{
NID nid = pApi->INode((LPCTSTR) str);
if (nid == -1)
{
// Invalid node name. This also throws suspicion on anything further
// down the line. Just break out of the loop.
break;
}
node.val = nid + idhFirst;
}
m_State.Push(node);
}
return;
}
void CHttpQuery::PushNodesLastSniffed(const CArray<int, int>& arr)
{
for (int i = 0; i < arr.GetSize(); i++)
{
CNode node;
node.cmd = idhFirst + arr[i];
node.val = 0;
node.sniffed = true;
m_State.Push(node);
}
}
void CHttpQuery::FinishInitFromServ(BCache *pApi, ILaunchTS *pLaunchTS)
{
ASSERT(pApi);
CNode node;
CString str;
HRESULT hRes;
HRESULT hResNode;
HRESULT hResState;
OLECHAR *poleProblem;
OLECHAR *poleNode;
OLECHAR *poleState;
OLECHAR *poleMachine;
OLECHAR *polePNPDevice;
OLECHAR *poleGuidClass;
OLECHAR *poleDeviceInstance;
///////////////////////////////////////////////////////////
// obtaining Machine, PNPDevice, GuidClass, DeviceInstance
//
hRes = pLaunchTS->GetMachine(&poleMachine);
if (S_FALSE == hRes || FAILED(hRes))
return;
m_strMachineID = poleMachine;
::SysFreeString(poleMachine);
hRes = pLaunchTS->GetPNPDevice(&polePNPDevice);
if (S_FALSE == hRes || FAILED(hRes))
return;
m_strPNPDeviceID = polePNPDevice;
::SysFreeString(polePNPDevice);
hRes = pLaunchTS->GetGuidClass(&poleGuidClass);
if (S_FALSE == hRes || FAILED(hRes))
return;
m_strGuidClass = poleGuidClass;
::SysFreeString(poleGuidClass);
hRes = pLaunchTS->GetDeviceInstance(&poleDeviceInstance);
if (S_FALSE == hRes || FAILED(hRes))
return;
m_strDeviceInstanceID = poleDeviceInstance;
::SysFreeString(poleDeviceInstance);
//
////////////////////////////////////////////////////////////
if (!pApi)
return;
if (!pApi->BValidNet())
pApi->ReadModel();
m_Size = 1; // I believe this accounts for the troubleshooting network name (JM 3/98)
m_nStatesFromServ = 0;
// The order that the nodes are set in the inference engine is important.
// >>> I (JM 3/14/98) don't understand the rest of this comment:
// Need the rest of the nodes inverted on the stack.
// The buttons can not be inverted here. When they are the back button
// stops working.
hRes = pLaunchTS->GetProblem(&poleProblem);
if (S_FALSE == hRes || FAILED(hRes))
return;
str = poleProblem;
SysFreeString(poleProblem);
node.cmd = pApi->CNode() + idhFirst; // Sets the problem state.
if (StrIsDigit((LPCTSTR) str))
node.val = _ttoi(str);
else
{
NID nidProblem = pApi->INode((LPCTSTR) str);
if (nidProblem == static_cast<NID>(-1))
{
// The specified problem node doesn't exist. Ignore it and any other nodes
// that follow.
return;
}
pApi->SetRunWithKnownProblem(true);
pApi->BNodeSetCurrent( nidProblem );
if (pApi->ELblNode() != ESTDLBL_problem )
{
// The specified problem node exists, but it's not a problem node.
// Ignore it and any other nodes that follow.
return;
}
IDH idhProblem = nidProblem + idhFirst;
node.val = idhProblem;
}
m_State.Push(node);
m_Size++;
m_aStatesFromServ[m_nStatesFromServ] = node;
m_nStatesFromServ++;
int iAnyNode = 0;
do
{
hResNode = pLaunchTS->GetNode((short)iAnyNode, &poleNode);
if (FAILED(hResNode) || S_FALSE == hResNode)
break;
str = poleNode;
SysFreeString(poleNode);
if (StrIsDigit((LPCTSTR) str))
node.cmd = _ttoi(str);
else
node.cmd = pApi->INode((LPCTSTR) str) + idhFirst;
hResState = pLaunchTS->GetState((short)iAnyNode, &poleState);
if (FAILED(hResState) || S_FALSE == hResState)
break;;
str = poleState;
SysFreeString(poleNode);
if (StrIsDigit((LPCTSTR) str))
node.val = _ttoi(str);
else
node.val = pApi->INode((LPCTSTR) str) + idhFirst;
m_State.Push(node);
m_Size++;
m_aStatesFromServ[m_nStatesFromServ] = node;
m_nStatesFromServ++;
iAnyNode++;
} while (true);
return;
}
// Restore states to where CHttpQuery::FinishInitFromServ() left them
void CHttpQuery::RestoreStatesFromServ()
{
UINT i;
for (i=0; i < m_nStatesFromServ; i++)
m_State.Push(m_aStatesFromServ[i]);
}
//
//
BOOL CHttpQuery::GetFirst(CString &strPut, CString &strValue)
{
BOOL bStatus = FALSE;
if (0 < m_Size)
{
bStatus = TRUE;
strPut = m_strCmd1;
strValue = m_strVal1;
m_CurrentUse = 0;
}
m_CurrentUse++;
return bStatus;
}
void CHttpQuery::SetFirst(CString &strCmd, CString &strVal)
{
m_Size = 1;
m_strCmd1 = strCmd;
m_strVal1 = strVal;
return;
}
//
//
BOOL CHttpQuery::GetNext(int &refedCmd, int &refedValue /*TCHAR *pCmd, TCHAR *pValue*/ )
{
BOOL bStatus;
CNode node;
// The stack direction was made to be reversable
// to support setting many nodes by an NT5 application using the TS Launcher.
if (false == m_bReverseStack)
bStatus = m_State.GetAt(m_CurrentUse, node);
else
bStatus = m_State.GetAt(m_Size - m_CurrentUse, node);
refedCmd = node.cmd;
refedValue = node.val;
m_CurrentUse++;
return bStatus;
}
void CHttpQuery::SetStackDirection()
{
if ((m_Size - m_CurrentUse) > 1)
m_bReverseStack = true;
else
m_bReverseStack = false;
}
/*
BOOL CHttpQuery::GetValue(int &Value, int index)
{
BOOL bRet = TRUE;
CNode node;
if (m_State.GetAt(index, node))
Value = node.val;
else
{
Value = NULL;
bRet = FALSE;
}
return bRet;
}
*/
BOOL CHttpQuery::GetValue1(int &Value)
{
BOOL bRet = TRUE;
CNode node;
if (false == m_bReverseStack)
{
if (m_State.GetAt(1, node))
{
Value = node.val;
}
else
{
Value = NULL;
bRet = FALSE;
}
}
else
{
if (m_State.GetAt(m_Size - 1, node))
{
Value = node.val;
}
else
{
Value = NULL;
bRet = FALSE;
}
}
return bRet;
}
CString CHttpQuery::GetTroubleShooter()
{
CString str = m_pvarVals[0].bstrVal;
return str;
}
CString CHttpQuery::GetFirstCmd()
{
CString str = m_pvarCmds[0].bstrVal;
return str;
}
BOOL CHttpQuery::BackUp(BCache *pApi, APGTSContext *pCtx)
{
ASSERT(pApi);
CNode node;
BOOL bBack = FALSE;
if (!m_State.Empty())
{
bBack = TRUE;
node = m_State.Pop();
if (!m_State.Empty())
{ // Can not uninstantiate the problem page, it is not a real node.
// Remove the node from the bnts network.
if (node.val < 100)
pApi->RemoveRecommendation(node.cmd - idhFirst);
if (node.sniffed) // skip all sniffed nodes by recursive call of the function
return BackUp(pApi, pCtx);
pCtx->BackUp(node.cmd - idhFirst, node.val);
}
else
{
pApi->RemoveRecommendation(node.val - idhFirst);
pCtx->BackUp(node.val - idhFirst, CBackupInfo::INVALID_BNTS_STATE);
}
}
return bBack;
}
void CHttpQuery::RemoveNodes(BCache *pApi)
{
CNode node;
while (!m_State.Empty())
{
node = m_State.Pop();
if (!m_State.Empty())
{
//VERIFY(pApi->BNodeSetCurrent(node.cmd - idhFirst));
//pApi->BNodeSet(-1, false);
pApi->RemoveRecommendation(node.cmd - idhFirst); // we need remove all data assosiated with previous path
}
else
{
//VERIFY(pApi->BNodeSetCurrent(node.val - idhFirst));
//pApi->BNodeSet(-1, false);
pApi->RemoveRecommendation(node.val - idhFirst); // we need remove all data assosiated with previous path
}
}
pApi->RemoveStates();
return;
}
void CHttpQuery::AddNodes(BCache *pApi)
{
CNode node;
RSStack<CNode>state;
if (m_State.PeakFirst(node))
{
do
{
state.Push(node);
} while (m_State.PeakNext(node));
}
if (!state.Empty())
{
node = state.Pop();
VERIFY(pApi->GTSAPI::BNodeSetCurrent(node.val - idhFirst));
pApi->GTSAPI::BNodeSet(1, false);
}
while (!state.Empty())
{
node = state.Pop();
if (node.val < 100) // We never instantiate the I don't know nodes.
{
VERIFY(pApi->GTSAPI::BNodeSetCurrent(node.cmd - idhFirst));
pApi->GTSAPI::BNodeSet(node.val, false);
}
}
return;
}
CString CHttpQuery::GetSubmitString(BCache *pApi)
{
ASSERT(NULL != pApi);
CNode node;
RSStack<CNode> stack;
CString str;
CString strGet = _T("");
if (m_State.PeakFirst(node))
{
do
{
stack.Push(node);
} while (m_State.PeakNext(node));
}
if (!stack.Empty())
{
node = stack.Pop();
if (pApi->BNodeSetCurrent(node.val - idhFirst))
{
strGet += _T("&");
strGet += CHOOSE_TS_PROBLEM_NODE;
strGet += _T("=");
pApi->NodeSymName();
strGet += pApi->SzcResult();
}
while (!stack.Empty())
{
node = stack.Pop();
if (pApi->BNodeSetCurrent(node.cmd - idhFirst))
{
strGet += _T("&");
pApi->NodeSymName();
strGet += pApi->SzcResult();
str.Format(_T("%d"), node.val);
strGet += _T("=") + str;
}
}
}
return strGet;
}
void CHttpQuery::Debug()
{
CNode node;
RSStack<CNode>state;
CString str;
if (m_State.PeakFirst(node))
{
do
{
str.Format(_T("Cmd %d Val %d"), node.cmd, node.val);
AfxMessageBox(str);
} while (m_State.PeakNext(node));
}
}
CString& CHttpQuery::GetMachine()
{
return m_strMachineID;
}
CString& CHttpQuery::GetPNPDevice()
{
return m_strPNPDeviceID;
}
CString& CHttpQuery::GetDeviceInstance()
{
return m_strDeviceInstanceID;
}
CString& CHttpQuery::GetGuidClass()
{
return m_strGuidClass;
}