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.

671 lines
15 KiB

  1. //
  2. // MODULE: APGTSQRY.CPP
  3. //
  4. // PURPOSE: Implementation file for PTS Query Parser
  5. //
  6. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  7. //
  8. //
  9. // NOTES:
  10. // 1. Based on Print Troubleshooter DLL
  11. //
  12. // Version Date By Comments
  13. //--------------------------------------------------------------------
  14. // V0.1 - RM Original
  15. // V0.2 6/4/97 RWM Local Version for Memphis
  16. // V0.3 04/09/98 JM/OK+ Local Version for NT5
  17. //
  18. //#include "windows.h"
  19. #include "stdafx.h"
  20. #include "time.h"
  21. #include "apgts.h"
  22. #include "bnts.h"
  23. #include "BackupInfo.h"
  24. #include "cachegen.h"
  25. #include "apgtsinf.h"
  26. #include "apgtscmd.h"
  27. #include "apgtshtx.h"
  28. #include "apgtscls.h"
  29. #include "ErrorEnums.h"
  30. #include "BasicException.h"
  31. #include "HttpQueryException.h"
  32. #include "Functions.h"
  33. #include "BackupInfo.h"
  34. #include <string.h>
  35. #include <stdlib.h>
  36. #include "LaunchServ.h"
  37. //
  38. //
  39. CHttpQuery::CHttpQuery()
  40. {
  41. m_pvarCmds = NULL;
  42. m_pvarVals = NULL;
  43. m_strCmd1 = _T("");
  44. m_strVal1 = _T("");
  45. m_CurrentUse = 0;
  46. m_Size = 0;
  47. m_bReverseStack = false;
  48. m_nStatesFromServ = 0;
  49. }
  50. //
  51. //
  52. CHttpQuery::~CHttpQuery()
  53. {
  54. }
  55. void CHttpQuery::ThrowBadParams(CString &str)
  56. {
  57. CHttpQueryException *pExc = new CHttpQueryException;
  58. #ifndef __DEBUG_HTTPQUERY_
  59. pExc->m_strError = _T("Script Error");
  60. #else
  61. pExc->m_strError = str;
  62. #endif
  63. throw pExc;
  64. return;
  65. }
  66. void CHttpQuery::Initialize(const VARIANT FAR& varCmds, const VARIANT FAR& varVals, short size)
  67. {
  68. #ifdef __DEBUG_HTTPQUERY_
  69. AfxMessageBox(_T("Cmd Variant Types:\n\n") + DecodeVariantTypes(varCmds.vt), MB_ICONINFORMATION);
  70. AfxMessageBox(_T("Value Variant Types:\n\n") + DecodeVariantTypes(varVals.vt), MB_ICONINFORMATION);
  71. #endif
  72. const VARIANT FAR *pVarCmds;
  73. const VARIANT FAR *pVarVals;
  74. if (VT_BYREF == (VT_BYREF & varCmds.vt) &&
  75. VT_VARIANT == (VT_VARIANT & varCmds.vt))
  76. {
  77. if (VT_ARRAY == (VT_ARRAY & varCmds.vt))
  78. pVarCmds = &varCmds;
  79. else
  80. pVarCmds = varCmds.pvarVal;
  81. }
  82. else
  83. {
  84. pVarCmds = NULL;
  85. CString str = _T("Cmd parameters from VB were not a variant or not by ref.");
  86. ASSERT(FALSE);
  87. TRACE(_T("%s\n"), str);
  88. ThrowBadParams(str);
  89. }
  90. if (VT_BYREF == (VT_BYREF & varVals.vt) &&
  91. VT_VARIANT == (VT_VARIANT & varVals.vt))
  92. {
  93. if (VT_ARRAY == (VT_ARRAY & varVals.vt))
  94. pVarVals = &varVals;
  95. else
  96. pVarVals = varVals.pvarVal;
  97. }
  98. else
  99. {
  100. pVarVals = NULL;
  101. CString str = _T("Cmd parameters from VB were not a variant or not by ref.");
  102. ASSERT(FALSE);
  103. TRACE(_T("%s\n"), str);
  104. ThrowBadParams(str);
  105. }
  106. if (VT_BYREF != (VT_BYREF & pVarCmds->vt) ||
  107. VT_ARRAY != (VT_ARRAY & pVarCmds->vt) ||
  108. VT_VARIANT != (0xFFF & pVarCmds->vt))
  109. {
  110. CString str = _T("Wrong Cmd parameters passed from VB.");
  111. ASSERT(FALSE);
  112. TRACE(_T("%s\n"), str);
  113. ThrowBadParams(str);
  114. }
  115. if (VT_BYREF != (VT_BYREF & pVarVals->vt) ||
  116. VT_ARRAY != (VT_ARRAY & pVarVals->vt) ||
  117. VT_VARIANT != (0xFFF & pVarVals->vt))
  118. {
  119. CString str = _T("Wrong Cmd parameters passed from VB.");
  120. ASSERT(FALSE);
  121. TRACE(_T("%s\n"), str);
  122. ThrowBadParams(str);
  123. }
  124. #ifdef __DEBUG_HTTPQUERY_
  125. AfxMessageBox(_T("Cmd Variant Types:\n\n") + DecodeVariantTypes(pVarCmds->vt), MB_ICONINFORMATION);
  126. AfxMessageBox(_T("Value Variant Types:\n\n") + DecodeVariantTypes(pVarVals->vt), MB_ICONINFORMATION);
  127. #endif
  128. SAFEARRAY *pArrCmds = *(pVarCmds->pparray);
  129. SAFEARRAY *pArrVals = *(pVarVals->pparray);
  130. #ifdef __DEBUG_HTTPQUERY_
  131. CString strSafe;
  132. strSafe.Format("Cmd Safe Array\n\nDim: %d\nfeatures:\n%s\nSize of the Elements: %ld",
  133. pArrCmds->cDims, (LPCTSTR) DecodeSafeArray(pArrCmds->fFeatures),
  134. pArrCmds->cbElements);
  135. AfxMessageBox(strSafe, MB_ICONINFORMATION);
  136. strSafe.Format("Val Safe Array\n\nDim: %d\nfeatures:\n%s\nSize of the Elements: %ld",
  137. pArrVals->cDims, (LPCTSTR) DecodeSafeArray(pArrVals->fFeatures),
  138. pArrVals->cbElements);
  139. AfxMessageBox(strSafe, MB_ICONINFORMATION);
  140. #endif
  141. if (0 != pArrCmds->rgsabound[0].lLbound || 0 != pArrVals->rgsabound[0].lLbound)
  142. {
  143. CString str = _T("Wrong Cmd parameters passed from VB. Lower bounds are wrong.");
  144. ASSERT(FALSE);
  145. TRACE(_T("%s\n"), str);
  146. ThrowBadParams(str);
  147. }
  148. if (pArrCmds->rgsabound[0].cElements != pArrVals->rgsabound[0].cElements)
  149. {
  150. CString str = _T("Wrong Cmd parameters passed from VB. Cmds upperbound != Vals upperbound.");
  151. ASSERT(FALSE);
  152. TRACE(_T("%s\n"), str);
  153. ThrowBadParams(str);
  154. }
  155. m_Size = size;
  156. #ifdef __DEBUG_HTTPQUERY_
  157. CString str;
  158. str.Format("Size: %d", m_Size);
  159. AfxMessageBox(str, MB_ICONINFORMATION);
  160. #endif
  161. m_pvarCmds = (VARIANT *) pArrCmds->pvData;
  162. m_pvarVals = (VARIANT *) pArrVals->pvData;
  163. if (0 != m_Size)
  164. {
  165. if (m_pvarCmds->vt != VT_BSTR || m_pvarVals->vt != VT_BSTR)
  166. {
  167. CString str;
  168. str.Format(_T("Wrong Cmd parameters passed from VB. Array of unexpected type.\n\n")
  169. _T("Cmd Type: %s\nVal Type: %s"),
  170. (LPCTSTR) DecodeVariantTypes(m_pvarCmds->vt),
  171. (LPCTSTR) DecodeVariantTypes(m_pvarVals->vt));
  172. ASSERT(FALSE);
  173. TRACE(_T("%s\n"), str);
  174. ThrowBadParams(str);
  175. }
  176. }
  177. CString strC = m_pvarCmds[0].bstrVal;
  178. CString strD = m_pvarVals[0].bstrVal;
  179. if (strC != m_strCmd1 || strD != m_strVal1)
  180. m_State.RemoveAll();
  181. m_strCmd1 = strC;
  182. m_strVal1 = strD;
  183. return;
  184. }
  185. BOOL CHttpQuery::StrIsDigit(LPCTSTR pSz)
  186. {
  187. BOOL bRet = TRUE;
  188. while (*pSz)
  189. {
  190. if (!_istdigit(*pSz))
  191. {
  192. bRet = FALSE;
  193. break;
  194. }
  195. pSz = _tcsinc(pSz);
  196. }
  197. return bRet;
  198. }
  199. void CHttpQuery::FinishInit(BCache *pApi, const VARIANT FAR& varCmds, const VARIANT FAR& varVals)
  200. {
  201. ASSERT(pApi);
  202. ASSERT(m_Size > 0);
  203. CNode node;
  204. CString str;
  205. if (!pApi)
  206. return;
  207. if (!pApi->BValidNet())
  208. pApi->ReadModel();
  209. m_bReverseStack = false;
  210. for (int x = 1; x < m_Size; x++)
  211. {
  212. // Read the command.
  213. str = m_pvarCmds[x].bstrVal;
  214. if (StrIsDigit((LPCTSTR) str))
  215. node.cmd = _ttoi(str);
  216. else if (0 == _tcscmp(CHOOSE_TS_PROBLEM_NODE, (LPCTSTR) str))
  217. node.cmd = pApi->CNode() + idhFirst;
  218. else if (0 == _tcscmp(TRY_TS_AT_MICROSOFT_SZ, (LPCTSTR) str))
  219. node.cmd = TRY_TS_AT_MICROSOFT_ID;
  220. else
  221. {
  222. NID nid = pApi->INode((LPCTSTR) str);
  223. if (nid == -1)
  224. {
  225. // Invalid node name. This also throws suspicion on anything further
  226. // down the line. Just break out of the loop.
  227. break;
  228. }
  229. node.cmd = nid + idhFirst;
  230. }
  231. // Read the value.
  232. str = m_pvarVals[x].bstrVal;
  233. if (StrIsDigit((LPCTSTR) str))
  234. node.val = _ttoi(str);
  235. else
  236. {
  237. NID nid = pApi->INode((LPCTSTR) str);
  238. if (nid == -1)
  239. {
  240. // Invalid node name. This also throws suspicion on anything further
  241. // down the line. Just break out of the loop.
  242. break;
  243. }
  244. node.val = nid + idhFirst;
  245. }
  246. m_State.Push(node);
  247. }
  248. return;
  249. }
  250. void CHttpQuery::PushNodesLastSniffed(const CArray<int, int>& arr)
  251. {
  252. for (int i = 0; i < arr.GetSize(); i++)
  253. {
  254. CNode node;
  255. node.cmd = idhFirst + arr[i];
  256. node.val = 0;
  257. node.sniffed = true;
  258. m_State.Push(node);
  259. }
  260. }
  261. void CHttpQuery::FinishInitFromServ(BCache *pApi, ILaunchTS *pLaunchTS)
  262. {
  263. ASSERT(pApi);
  264. CNode node;
  265. CString str;
  266. HRESULT hRes;
  267. HRESULT hResNode;
  268. HRESULT hResState;
  269. OLECHAR *poleProblem;
  270. OLECHAR *poleNode;
  271. OLECHAR *poleState;
  272. OLECHAR *poleMachine;
  273. OLECHAR *polePNPDevice;
  274. OLECHAR *poleGuidClass;
  275. OLECHAR *poleDeviceInstance;
  276. ///////////////////////////////////////////////////////////
  277. // obtaining Machine, PNPDevice, GuidClass, DeviceInstance
  278. //
  279. hRes = pLaunchTS->GetMachine(&poleMachine);
  280. if (S_FALSE == hRes || FAILED(hRes))
  281. return;
  282. m_strMachineID = poleMachine;
  283. ::SysFreeString(poleMachine);
  284. hRes = pLaunchTS->GetPNPDevice(&polePNPDevice);
  285. if (S_FALSE == hRes || FAILED(hRes))
  286. return;
  287. m_strPNPDeviceID = polePNPDevice;
  288. ::SysFreeString(polePNPDevice);
  289. hRes = pLaunchTS->GetGuidClass(&poleGuidClass);
  290. if (S_FALSE == hRes || FAILED(hRes))
  291. return;
  292. m_strGuidClass = poleGuidClass;
  293. ::SysFreeString(poleGuidClass);
  294. hRes = pLaunchTS->GetDeviceInstance(&poleDeviceInstance);
  295. if (S_FALSE == hRes || FAILED(hRes))
  296. return;
  297. m_strDeviceInstanceID = poleDeviceInstance;
  298. ::SysFreeString(poleDeviceInstance);
  299. //
  300. ////////////////////////////////////////////////////////////
  301. if (!pApi)
  302. return;
  303. if (!pApi->BValidNet())
  304. pApi->ReadModel();
  305. m_Size = 1; // I believe this accounts for the troubleshooting network name (JM 3/98)
  306. m_nStatesFromServ = 0;
  307. // The order that the nodes are set in the inference engine is important.
  308. // >>> I (JM 3/14/98) don't understand the rest of this comment:
  309. // Need the rest of the nodes inverted on the stack.
  310. // The buttons can not be inverted here. When they are the back button
  311. // stops working.
  312. hRes = pLaunchTS->GetProblem(&poleProblem);
  313. if (S_FALSE == hRes || FAILED(hRes))
  314. return;
  315. str = poleProblem;
  316. SysFreeString(poleProblem);
  317. node.cmd = pApi->CNode() + idhFirst; // Sets the problem state.
  318. if (StrIsDigit((LPCTSTR) str))
  319. node.val = _ttoi(str);
  320. else
  321. {
  322. NID nidProblem = pApi->INode((LPCTSTR) str);
  323. if (nidProblem == static_cast<NID>(-1))
  324. {
  325. // The specified problem node doesn't exist. Ignore it and any other nodes
  326. // that follow.
  327. return;
  328. }
  329. pApi->SetRunWithKnownProblem(true);
  330. pApi->BNodeSetCurrent( nidProblem );
  331. if (pApi->ELblNode() != ESTDLBL_problem )
  332. {
  333. // The specified problem node exists, but it's not a problem node.
  334. // Ignore it and any other nodes that follow.
  335. return;
  336. }
  337. IDH idhProblem = nidProblem + idhFirst;
  338. node.val = idhProblem;
  339. }
  340. m_State.Push(node);
  341. m_Size++;
  342. m_aStatesFromServ[m_nStatesFromServ] = node;
  343. m_nStatesFromServ++;
  344. int iAnyNode = 0;
  345. do
  346. {
  347. hResNode = pLaunchTS->GetNode((short)iAnyNode, &poleNode);
  348. if (FAILED(hResNode) || S_FALSE == hResNode)
  349. break;
  350. str = poleNode;
  351. SysFreeString(poleNode);
  352. if (StrIsDigit((LPCTSTR) str))
  353. node.cmd = _ttoi(str);
  354. else
  355. node.cmd = pApi->INode((LPCTSTR) str) + idhFirst;
  356. hResState = pLaunchTS->GetState((short)iAnyNode, &poleState);
  357. if (FAILED(hResState) || S_FALSE == hResState)
  358. break;;
  359. str = poleState;
  360. SysFreeString(poleNode);
  361. if (StrIsDigit((LPCTSTR) str))
  362. node.val = _ttoi(str);
  363. else
  364. node.val = pApi->INode((LPCTSTR) str) + idhFirst;
  365. m_State.Push(node);
  366. m_Size++;
  367. m_aStatesFromServ[m_nStatesFromServ] = node;
  368. m_nStatesFromServ++;
  369. iAnyNode++;
  370. } while (true);
  371. return;
  372. }
  373. // Restore states to where CHttpQuery::FinishInitFromServ() left them
  374. void CHttpQuery::RestoreStatesFromServ()
  375. {
  376. UINT i;
  377. for (i=0; i < m_nStatesFromServ; i++)
  378. m_State.Push(m_aStatesFromServ[i]);
  379. }
  380. //
  381. //
  382. BOOL CHttpQuery::GetFirst(CString &strPut, CString &strValue)
  383. {
  384. BOOL bStatus = FALSE;
  385. if (0 < m_Size)
  386. {
  387. bStatus = TRUE;
  388. strPut = m_strCmd1;
  389. strValue = m_strVal1;
  390. m_CurrentUse = 0;
  391. }
  392. m_CurrentUse++;
  393. return bStatus;
  394. }
  395. void CHttpQuery::SetFirst(CString &strCmd, CString &strVal)
  396. {
  397. m_Size = 1;
  398. m_strCmd1 = strCmd;
  399. m_strVal1 = strVal;
  400. return;
  401. }
  402. //
  403. //
  404. BOOL CHttpQuery::GetNext(int &refedCmd, int &refedValue /*TCHAR *pCmd, TCHAR *pValue*/ )
  405. {
  406. BOOL bStatus;
  407. CNode node;
  408. // The stack direction was made to be reversable
  409. // to support setting many nodes by an NT5 application using the TS Launcher.
  410. if (false == m_bReverseStack)
  411. bStatus = m_State.GetAt(m_CurrentUse, node);
  412. else
  413. bStatus = m_State.GetAt(m_Size - m_CurrentUse, node);
  414. refedCmd = node.cmd;
  415. refedValue = node.val;
  416. m_CurrentUse++;
  417. return bStatus;
  418. }
  419. void CHttpQuery::SetStackDirection()
  420. {
  421. if ((m_Size - m_CurrentUse) > 1)
  422. m_bReverseStack = true;
  423. else
  424. m_bReverseStack = false;
  425. }
  426. /*
  427. BOOL CHttpQuery::GetValue(int &Value, int index)
  428. {
  429. BOOL bRet = TRUE;
  430. CNode node;
  431. if (m_State.GetAt(index, node))
  432. Value = node.val;
  433. else
  434. {
  435. Value = NULL;
  436. bRet = FALSE;
  437. }
  438. return bRet;
  439. }
  440. */
  441. BOOL CHttpQuery::GetValue1(int &Value)
  442. {
  443. BOOL bRet = TRUE;
  444. CNode node;
  445. if (false == m_bReverseStack)
  446. {
  447. if (m_State.GetAt(1, node))
  448. {
  449. Value = node.val;
  450. }
  451. else
  452. {
  453. Value = NULL;
  454. bRet = FALSE;
  455. }
  456. }
  457. else
  458. {
  459. if (m_State.GetAt(m_Size - 1, node))
  460. {
  461. Value = node.val;
  462. }
  463. else
  464. {
  465. Value = NULL;
  466. bRet = FALSE;
  467. }
  468. }
  469. return bRet;
  470. }
  471. CString CHttpQuery::GetTroubleShooter()
  472. {
  473. CString str = m_pvarVals[0].bstrVal;
  474. return str;
  475. }
  476. CString CHttpQuery::GetFirstCmd()
  477. {
  478. CString str = m_pvarCmds[0].bstrVal;
  479. return str;
  480. }
  481. BOOL CHttpQuery::BackUp(BCache *pApi, APGTSContext *pCtx)
  482. {
  483. ASSERT(pApi);
  484. CNode node;
  485. BOOL bBack = FALSE;
  486. if (!m_State.Empty())
  487. {
  488. bBack = TRUE;
  489. node = m_State.Pop();
  490. if (!m_State.Empty())
  491. { // Can not uninstantiate the problem page, it is not a real node.
  492. // Remove the node from the bnts network.
  493. if (node.val < 100)
  494. pApi->RemoveRecommendation(node.cmd - idhFirst);
  495. if (node.sniffed) // skip all sniffed nodes by recursive call of the function
  496. return BackUp(pApi, pCtx);
  497. pCtx->BackUp(node.cmd - idhFirst, node.val);
  498. }
  499. else
  500. {
  501. pApi->RemoveRecommendation(node.val - idhFirst);
  502. pCtx->BackUp(node.val - idhFirst, CBackupInfo::INVALID_BNTS_STATE);
  503. }
  504. }
  505. return bBack;
  506. }
  507. void CHttpQuery::RemoveNodes(BCache *pApi)
  508. {
  509. CNode node;
  510. while (!m_State.Empty())
  511. {
  512. node = m_State.Pop();
  513. if (!m_State.Empty())
  514. {
  515. //VERIFY(pApi->BNodeSetCurrent(node.cmd - idhFirst));
  516. //pApi->BNodeSet(-1, false);
  517. pApi->RemoveRecommendation(node.cmd - idhFirst); // we need remove all data assosiated with previous path
  518. }
  519. else
  520. {
  521. //VERIFY(pApi->BNodeSetCurrent(node.val - idhFirst));
  522. //pApi->BNodeSet(-1, false);
  523. pApi->RemoveRecommendation(node.val - idhFirst); // we need remove all data assosiated with previous path
  524. }
  525. }
  526. pApi->RemoveStates();
  527. return;
  528. }
  529. void CHttpQuery::AddNodes(BCache *pApi)
  530. {
  531. CNode node;
  532. RSStack<CNode>state;
  533. if (m_State.PeakFirst(node))
  534. {
  535. do
  536. {
  537. state.Push(node);
  538. } while (m_State.PeakNext(node));
  539. }
  540. if (!state.Empty())
  541. {
  542. node = state.Pop();
  543. VERIFY(pApi->GTSAPI::BNodeSetCurrent(node.val - idhFirst));
  544. pApi->GTSAPI::BNodeSet(1, false);
  545. }
  546. while (!state.Empty())
  547. {
  548. node = state.Pop();
  549. if (node.val < 100) // We never instantiate the I don't know nodes.
  550. {
  551. VERIFY(pApi->GTSAPI::BNodeSetCurrent(node.cmd - idhFirst));
  552. pApi->GTSAPI::BNodeSet(node.val, false);
  553. }
  554. }
  555. return;
  556. }
  557. CString CHttpQuery::GetSubmitString(BCache *pApi)
  558. {
  559. ASSERT(NULL != pApi);
  560. CNode node;
  561. RSStack<CNode> stack;
  562. CString str;
  563. CString strGet = _T("");
  564. if (m_State.PeakFirst(node))
  565. {
  566. do
  567. {
  568. stack.Push(node);
  569. } while (m_State.PeakNext(node));
  570. }
  571. if (!stack.Empty())
  572. {
  573. node = stack.Pop();
  574. if (pApi->BNodeSetCurrent(node.val - idhFirst))
  575. {
  576. strGet += _T("&");
  577. strGet += CHOOSE_TS_PROBLEM_NODE;
  578. strGet += _T("=");
  579. pApi->NodeSymName();
  580. strGet += pApi->SzcResult();
  581. }
  582. while (!stack.Empty())
  583. {
  584. node = stack.Pop();
  585. if (pApi->BNodeSetCurrent(node.cmd - idhFirst))
  586. {
  587. strGet += _T("&");
  588. pApi->NodeSymName();
  589. strGet += pApi->SzcResult();
  590. str.Format(_T("%d"), node.val);
  591. strGet += _T("=") + str;
  592. }
  593. }
  594. }
  595. return strGet;
  596. }
  597. void CHttpQuery::Debug()
  598. {
  599. CNode node;
  600. RSStack<CNode>state;
  601. CString str;
  602. if (m_State.PeakFirst(node))
  603. {
  604. do
  605. {
  606. str.Format(_T("Cmd %d Val %d"), node.cmd, node.val);
  607. AfxMessageBox(str);
  608. } while (m_State.PeakNext(node));
  609. }
  610. }
  611. CString& CHttpQuery::GetMachine()
  612. {
  613. return m_strMachineID;
  614. }
  615. CString& CHttpQuery::GetPNPDevice()
  616. {
  617. return m_strPNPDeviceID;
  618. }
  619. CString& CHttpQuery::GetDeviceInstance()
  620. {
  621. return m_strDeviceInstanceID;
  622. }
  623. CString& CHttpQuery::GetGuidClass()
  624. {
  625. return m_strGuidClass;
  626. }