Leaked source code of windows server 2003
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.

1246 lines
30 KiB

  1. //
  2. // MODULE: APGTSINF.CPP
  3. //
  4. // PURPOSE: Inference Engine Interface
  5. //
  6. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  7. //
  8. // COMPANY: Saltmine Creative, Inc. (206)-633-4743 [email protected]
  9. //
  10. // AUTHOR: Roman Mach
  11. // Modified By: Richard Meadows
  12. //
  13. // ORIGINAL DATE: 8-2-96
  14. // Modified Date: 6-3-97
  15. //
  16. // NOTES:
  17. // 1. Based on Print Troubleshooter DLL
  18. //
  19. // Version Date By Comments
  20. //--------------------------------------------------------------------
  21. // V0.1 - RM Original
  22. // V0.2 6/4/97 RWM Local Version for Memphis
  23. // V0.3 04/09/98 JM/OK+ Local Version for NT5
  24. //#include "windows.h"
  25. #include "stdafx.h"
  26. #include "time.h"
  27. #include "apgts.h"
  28. #include "ErrorEnums.h"
  29. #include "bnts.h"
  30. #include "BackupInfo.h"
  31. #include "cachegen.h"
  32. #include "apgtsinf.h"
  33. #include "apgtscmd.h"
  34. #include "apgtshtx.h"
  35. #include "apgtscls.h"
  36. #include "TSHOOT.h"
  37. //-----------------
  38. //
  39. #define CelemArray(rgtype) (sizeof(rgtype) / sizeof(rgtype[0]))
  40. CInfer::CInfer( CString *pCtxt)
  41. {
  42. m_bHttp = FALSE;
  43. m_pCtxt = pCtxt;
  44. m_bService = FALSE;
  45. m_nidPreloadCheck = 0;
  46. m_pResult = new CString();
  47. m_pCtmp = new CString();
  48. m_pSearchStr = new CString();
  49. m_ilineStat = 0;
  50. m_cnidSkip = 0;
  51. m_fDone = FALSE;
  52. m_ishowService = 0;
  53. m_idhQuestion = 0;
  54. // m_cnid = CelemArray(m_rgnid);
  55. m_problemAsk = FALSE;
  56. m_problem[0] = '\0';
  57. m_cShooters = 0;
  58. m_iShooter = 0;
  59. m_aShooters.RemoveAll();
  60. m_SkippedTwice.InitHashTable(7);
  61. m_api = NULL;
  62. }
  63. //
  64. //m_bFirstShooter
  65. CInfer::~CInfer()
  66. {
  67. if (m_pResult)
  68. delete m_pResult;
  69. if (m_pCtmp)
  70. delete m_pCtmp;
  71. if (m_pSearchStr)
  72. delete m_pSearchStr;
  73. m_SkippedTwice.RemoveAll();
  74. }
  75. //
  76. //
  77. DWORD CInfer::Initialize(/*CSearchForm *pBESearch*/)
  78. {
  79. // m_pBESearch = pBESearch;
  80. CString strTxt;
  81. if (m_pResult == NULL)
  82. return (EV_GTS_ERROR_INF_NO_MEM);
  83. m_max_rec = 0;
  84. return (0);
  85. }
  86. //
  87. //
  88. VOID CInfer::SetBelief(BCache *pAPI)
  89. {
  90. m_api = pAPI;
  91. // m_api->ResetNodes();
  92. // save count of nodes
  93. m_acnid = m_api->CNode();
  94. // reset preload check
  95. m_nidPreloadCheck = 0;
  96. }
  97. //
  98. //
  99. /*
  100. EC CInfer::GetExtendedError()
  101. {
  102. return m_uInfErr;
  103. }
  104. */
  105. //
  106. //
  107. VOID CInfer::AssertFailed(TSZC szcFile, UINT iline, TSZC szcCond, BOOL fFatal)
  108. {
  109. CString strTxt;
  110. strTxt.LoadString(IDS_ER_ASSERT_FAILED);
  111. PrintString(_T("%s(%u): %s %s\n"), szcFile, iline, (LPCTSTR) strTxt, szcCond);
  112. //exit(1);
  113. }
  114. //
  115. //
  116. void CInfer::SetProblemAsk()
  117. {
  118. m_problemAsk = TRUE;
  119. }
  120. //
  121. //
  122. void CInfer::ClearProblemAsk()
  123. {
  124. m_problemAsk = FALSE;
  125. }
  126. /*
  127. * METHOD: EvalData
  128. *
  129. * PURPOSE: This is used by the template execution unit when it needs to evaluate
  130. * a variable within a template. Variables are usually evaluated by a
  131. * <! display ' tag. Returns a string with the text of the variable
  132. * evaluated
  133. *
  134. */
  135. TCHAR *CInfer::EvalData(UINT var_index)
  136. {
  137. BOOL bSkipped;
  138. int val;
  139. *m_pCtmp = _T("");
  140. //AfxDebugBreak();
  141. switch (var_index) {
  142. case PROBLEM_ASK_INDEX:
  143. if (m_problemAsk) // we want to show first set of questions
  144. return(NULL);
  145. else
  146. return(m_problem);
  147. break;
  148. case RECOMMENDATIONS_INDEX:
  149. FxGetNode(m_rgnid[m_cur_rec],FALSE, m_pCtmp);
  150. break;
  151. case STATE_INDEX:
  152. FxGetState(m_pCtmp);
  153. break;
  154. case QUESTIONS_INDEX:
  155. {
  156. UINT inid;
  157. if ( GetForcedRecommendation() != SNIFF_INVALID_NODE_ID )
  158. {
  159. // we already have a recommendation from a sniffer
  160. GetIdhPage(GetForcedRecommendation() + idhFirst, m_pCtmp);
  161. }
  162. else
  163. {
  164. if (m_problemAsk) // show first page (radio-button list of possible problems)
  165. {
  166. GetIdhProblemPage(m_api->GetProblemAsk(), m_pCtmp);
  167. }
  168. else
  169. {
  170. int RecommendRes = Finish(m_pCtmp);
  171. if ( RECOMMEND_SUCCESS == RecommendRes ) // Normal
  172. { // The first node is the most likely.
  173. // Skip 102 nodes.
  174. for (inid=0; inid< m_cnid; inid++)
  175. {
  176. if (!(bSkipped = FSkip(m_question_rgnid[inid])) || (m_ishowService != 0))
  177. {
  178. // Do not show skipped nodes more that once.
  179. // Will end up in a endless loop.
  180. if (!m_SkippedTwice.Lookup(m_question_rgnid[inid], val))
  181. {
  182. if (bSkipped)
  183. m_SkippedTwice.SetAt(m_question_rgnid[inid], 1);
  184. if (!m_api->IsReverse()) // we're moving forward
  185. {
  186. //
  187. // Check if this node is sniffed
  188. //
  189. int state = SNIFF_INVALID_STATE;
  190. int nid = m_question_rgnid[inid];
  191. if (m_api->GetState(nid, &state)) // node that we're about to display turbed out to be sniffed
  192. {
  193. if (m_api->NodeSet(nid, state, false)) // set sniffed node current and set its state
  194. {
  195. m_api->SetAdditionalDataOnNodeSet(nid);
  196. RecommendRes = m_api->GTSGetRecommendations(m_cnid, m_question_rgnid, true);
  197. if ( RECOMMEND_SUCCESS == RecommendRes )
  198. {
  199. // re-execute loop again
  200. inid = 0;
  201. continue;
  202. }
  203. else
  204. {
  205. goto NO_SUCCESS;
  206. }
  207. }
  208. }
  209. //
  210. }
  211. GetIdhPage(m_question_rgnid[inid]+ idhFirst ,m_pCtmp);
  212. return(m_pCtmp->GetBuffer(m_pCtmp->GetLength()));
  213. }
  214. }
  215. }
  216. if (m_cnidSkip != 0)
  217. {
  218. /*
  219. // Going to show the skipped nodes message only one time.
  220. // Otherwise, they will get stuck on the skipped nodes message page.
  221. if (m_cnidSkip > (unsigned) m_SkippedTwice.GetCount())
  222. GetSkippedNodesMsg(_T("Skipped Node"), m_pCtmp);
  223. else
  224. GetIdhPage(nidService + idhFirst, m_pCtmp);
  225. */
  226. // Leave them in a better loop.
  227. m_SkippedTwice.RemoveAll();
  228. GetSkippedNodesMsg(_T("Skipped Node"), m_pCtmp);
  229. }
  230. else
  231. {
  232. GetIdhPage(nidService + idhFirst, m_pCtmp);
  233. }
  234. }
  235. NO_SUCCESS:
  236. // recommendation error handling
  237. //
  238. if (RECOMMEND_IMPOSSIBLE == RecommendRes)
  239. GetImpossibleNodesMsg(_T("Impossible"), m_pCtmp);
  240. if (RECOMMEND_NO_MORE_DATA == RecommendRes)
  241. GetIdhPage(IDH_FAIL, m_pCtmp);
  242. }
  243. }
  244. }
  245. break;
  246. case TROUBLE_SHOOTER_INDEX:
  247. GetTS(m_pCtmp);
  248. break;
  249. default:
  250. return(_T(""));
  251. }
  252. return(m_pCtmp->GetBuffer(m_pCtmp->GetLength()));
  253. }
  254. /*
  255. GetTS is used when all of the registered trouble shooters are displayed.
  256. */
  257. void CInfer::GetTS(CString *pCtmp)
  258. {
  259. TShooter tShooter;
  260. tShooter = m_aShooters.GetAt(m_iShooter);
  261. if (m_iShooter < m_cShooters)
  262. AfxFormatString2(*pCtmp, IDS_FPA_TS_BUTTON, tShooter.m_szName,
  263. tShooter.m_szDisplayName);
  264. else
  265. *pCtmp = _T("");
  266. m_iShooter++;
  267. }
  268. /*
  269. * METHOD: InitVar
  270. *
  271. * PURPOSE: This is called to initialize a variable in the template. It
  272. * is mainly called by a 'forany' command.
  273. *
  274. * RETURNS - flag indicating if variable is initialized
  275. *
  276. */
  277. BOOL CInfer::InitVar(UINT var_index)
  278. {
  279. switch( var_index) {
  280. case PROBLEM_ASK_INDEX:
  281. break;
  282. case RECOMMENDATIONS_INDEX:
  283. m_cur_rec = 0;
  284. if (m_max_rec == m_cur_rec)
  285. return FALSE;
  286. break;
  287. case STATE_INDEX:
  288. FxInitState(m_rgnid[m_cur_rec]);
  289. break;
  290. case QUESTIONS_INDEX:
  291. return m_api->GTSGetRecommendations(m_cnid,m_question_rgnid);
  292. break;
  293. case BACK_INDEX:
  294. return FALSE;
  295. case TROUBLE_SHOOTER_INDEX:
  296. m_iShooter = 0;
  297. return TRUE;
  298. break;
  299. default:
  300. return FALSE;
  301. }
  302. return TRUE;
  303. }
  304. /*
  305. * METHOD: NextVar
  306. *
  307. * PURPOSE: Used by the 'forany' command to increment to the next variable in a
  308. * variable list. Returns FALSE when their are no more variable
  309. *
  310. *
  311. */
  312. BOOL CInfer::NextVar(UINT var_index)
  313. {
  314. switch (var_index) {
  315. case PROBLEM_ASK_INDEX:
  316. return FALSE;
  317. case RECOMMENDATIONS_INDEX:
  318. m_cur_rec++;
  319. if (m_cur_rec < m_max_rec)
  320. return TRUE;
  321. else
  322. return FALSE;
  323. break;
  324. case STATE_INDEX:
  325. m_cur_ist++;
  326. if (m_cur_ist <= m_cur_cst)
  327. return TRUE;
  328. else{
  329. return FALSE;
  330. }
  331. break;
  332. case QUESTIONS_INDEX:
  333. return FALSE; // only one set
  334. case BACK_INDEX:
  335. return FALSE;
  336. case TROUBLE_SHOOTER_INDEX:
  337. if (m_cShooters > m_iShooter)
  338. return TRUE;
  339. else
  340. return FALSE;
  341. default:
  342. return FALSE;
  343. }
  344. return TRUE;
  345. }
  346. /*
  347. * METHOD: FxGetNode
  348. *
  349. * PURPOSE: This is used to get the '$Recommendation'. A Recommendation is
  350. * basically the name of the node in a belief network.
  351. *
  352. */
  353. BOOL CInfer::FxGetNode(NID nid, BOOL fStatus, CString *cstr) const
  354. {
  355. BOOL bRet;
  356. CString strTemp;
  357. bRet = m_api->BNodeSetCurrent(nid);
  358. if (bRet)
  359. {
  360. m_api->NodeFullName();
  361. strTemp = m_api->SzcResult();
  362. *cstr += strTemp;
  363. }
  364. return bRet;
  365. }
  366. /*
  367. * METHOD: FxGetState
  368. *
  369. * PURPOSE: This will print out the label of the state of a node. This label
  370. * corresponds to the possible choices of that node. NOTE: This
  371. * routine requires that an InitState be called sometime before to
  372. * setup some variables.
  373. *
  374. */
  375. void CInfer::FxGetState(CString *cstr)
  376. {
  377. CString strTemp;
  378. if (m_cur_ist > m_cur_cst)
  379. return;
  380. if (FSkip(m_rgnid[m_cur_rec]) ) // a 102 was selected
  381. m_cur_state_set = m_cur_cst;
  382. if (m_cur_ist == m_cur_cst)
  383. {
  384. WriteResult(m_rgnid[m_cur_rec] +idhFirst, 102, m_cur_ist == m_cur_state_set, _T("Unknown"), cstr);
  385. return;
  386. }
  387. ESTDLBL lbl;
  388. m_api->BNodeSetCurrent(m_rgnid[m_cur_rec]);
  389. lbl = m_api->ELblNode();
  390. if (lbl == ESTDLBL_fixobs || lbl == ESTDLBL_fixunobs)
  391. {
  392. if (!FSkip(m_rgnid[m_cur_rec]) )
  393. m_cur_state_set = 0;
  394. m_cur_ist = 0;
  395. m_api->NodeStateName(m_cur_ist);
  396. strTemp = m_api->SzcResult();
  397. WriteResult(m_rgnid[m_cur_rec] +idhFirst, m_cur_ist, m_cur_ist == m_cur_state_set, (LPCTSTR) strTemp, cstr);
  398. m_cur_ist = m_cur_cst -1;
  399. return;
  400. }
  401. m_api->NodeStateName(m_cur_ist);
  402. strTemp = m_api->SzcResult();
  403. WriteResult(m_rgnid[m_cur_rec] +idhFirst, m_cur_ist, m_cur_ist == m_cur_state_set, (LPCTSTR) strTemp, cstr);
  404. return;
  405. }
  406. //
  407. //
  408. void CInfer::FxInitState(NID nid)
  409. {
  410. UINT cst;
  411. UINT istSet = -1;
  412. m_api->BNodeSetCurrent(nid);
  413. cst = m_api->INodeCst();
  414. m_api->BNodeSetCurrent(nid);
  415. m_cur_state_set = m_api->INodeState();
  416. m_cur_cst = cst;
  417. m_cur_ist = 0;
  418. }
  419. #define SZ_WORKED _T("101")
  420. #define SZ_FAILED _T("0")
  421. #define SZ_YES _T("0")
  422. #define SZ_NO _T("1")
  423. #define SZ_UNKNOWN _T("102")
  424. #define SZ_ANY _T("103")
  425. #define SZ_MICRO _T("104")
  426. #define SZ_CHECKED _T("CHECKED")
  427. void inline CInfer::GetNextButton(CString &strNext)
  428. {
  429. if (m_api->BNetPropItemStr(HTK_NEXT_BTN, 0))
  430. strNext = m_api->SzcResult();
  431. else
  432. strNext = _T("Next");
  433. return;
  434. }
  435. void inline CInfer::GetBackButton(CString &strBack)
  436. {
  437. if (m_api->BNetPropItemStr(HTK_BACK_BTN, 0))
  438. strBack = m_api->SzcResult();
  439. else
  440. strBack = _T("Back");
  441. return;
  442. }
  443. void inline CInfer::GetStartButton(CString &strStart)
  444. {
  445. if (m_api->BNetPropItemStr(HTK_START_BTN, 0))
  446. strStart = m_api->SzcResult();
  447. else
  448. strStart = _T("Start Over");
  449. return;
  450. }
  451. void CInfer::GetStd3ButtonEnList(CString *cstr, bool bIncludeBackButton, bool bIncludeNextButton, bool bIncludeStartButton)
  452. {
  453. CString strBtnPart1 = "<INPUT class=\"standard\" ";
  454. CString strBack;
  455. CString strNext;
  456. CString strStart;
  457. GetBackButton(strBack);
  458. GetNextButton(strNext);
  459. GetStartButton(strStart);
  460. #if 0
  461. // just for debugging whether BACK button will show.
  462. char buf[256];
  463. *cstr += "<br>DEBUG bIncludeBackButton = ";
  464. *cstr += bIncludeBackButton ? "true. " : "false. ";
  465. *cstr += "<br>DEBUG m_api->StatesNowSet() = ";
  466. sprintf(buf, "%d", m_api->StatesNowSet());
  467. *cstr += buf;
  468. *cstr += "<br>m_api->StatesFromServ() = ";
  469. sprintf(buf, "%d", m_api->StatesFromServ());
  470. *cstr += buf;
  471. *cstr += "<br>m_cnidSkip = ";
  472. sprintf(buf, "%d", m_cnidSkip);
  473. *cstr += buf;
  474. *cstr += "<br>END DEBUG<br>";
  475. #endif
  476. *cstr += "</TABLE>\n<P><NOBR>";
  477. if (bIncludeBackButton)
  478. {
  479. *cstr += strBtnPart1;
  480. *cstr += "TYPE=BUTTON VALUE=";
  481. *cstr += "\"<&nbsp;&nbsp;";
  482. *cstr += strBack;
  483. *cstr += "&nbsp;\" onclick=\"previous()\">";
  484. }
  485. if (bIncludeNextButton)
  486. {
  487. *cstr += strBtnPart1;
  488. *cstr += "TYPE=SUBMIT VALUE=";
  489. *cstr += "\"&nbsp;";
  490. *cstr += strNext;
  491. *cstr += "&nbsp;&nbsp;>&nbsp;\">";
  492. }
  493. if (bIncludeStartButton)
  494. {
  495. *cstr += strBtnPart1;
  496. *cstr += "TYPE=BUTTON VALUE=";
  497. *cstr += "\"";
  498. *cstr += strStart;
  499. *cstr += "\" OnClick=\"starter()\"></NOBR><BR>\n";
  500. }
  501. return;
  502. }
  503. bool CInfer::BelongsOnProblemPage(int index)
  504. {
  505. VERIFY(m_api->BNodeSetCurrent(index));
  506. if (m_api->ELblNode() != ESTDLBL_problem)
  507. return false;
  508. // It's a problem node. Belongs unless H_PROB_SPECIAL_STR property contains
  509. // the string "hide"
  510. if (m_api->BNodePropItemStr(H_PROB_SPECIAL_STR, 0))
  511. return (_tcsstr(m_api->SzcResult(), _T("hide")) == NULL);
  512. else
  513. return true; // Doesn't even have an H_PROB_SPECIAL_STR
  514. }
  515. VOID CInfer::GetIdhProblemPage(IDH idh, CString *cstr)
  516. {
  517. CString strTxt;
  518. CString strIdh;
  519. CString strNext;
  520. strIdh.Format(_T("%d"), idhFirst + m_api->CNode());
  521. AfxFormatString2(strTxt, IDS_HTM_IDH1, (LPCTSTR) strIdh, _T("ProblemAsk"));
  522. *cstr += strTxt;
  523. //AfxDebugBreak();
  524. m_api->BNetPropItemStr(H_PROB_HD_STR, 0);
  525. AfxFormatString1(strTxt, IDS_HTM_HEADER1, m_api->SzcResult());
  526. *cstr += strTxt;
  527. strTxt.LoadString(IDS_HTM_ST_LIST1);
  528. *cstr += strTxt;
  529. for(int index = 0; index < m_api->CNode(); index++)
  530. {
  531. VERIFY(m_api->BNodeSetCurrent(index));
  532. if (BelongsOnProblemPage(index))
  533. {
  534. m_api->NodeSymName();
  535. AfxFormatString2(strTxt, IDS_HTM_RADIO1A, (LPCTSTR) strIdh, m_api->SzcResult());
  536. *cstr += strTxt;
  537. // If going back and this state was selected, write "Checked"
  538. if (m_Backup.Check(index))
  539. *cstr += SZ_CHECKED;
  540. VERIFY(m_api->BNodePropItemStr(H_PROB_TXT_STR, 0));
  541. AfxFormatString1(strTxt, IDS_HTM_RADIO1B, m_api->SzcResult());
  542. *cstr += strTxt;
  543. }
  544. }
  545. GetNextButton(strNext);
  546. AfxFormatString1(strTxt, IDS_HTM_EN_LIST1, (LPCTSTR) strNext);
  547. *cstr += strTxt;
  548. return;
  549. }
  550. //
  551. //
  552. VOID CInfer::GetFixRadios(LPCTSTR szIdh, CString *cstr)
  553. {
  554. CString strTxt;
  555. AfxFormatString2(strTxt, IDS_HTM_RADIO2A, szIdh, SZ_WORKED);
  556. if (m_api->BNodePropItemStr(H_ST_NORM_TXT_STR, 0))
  557. {
  558. *cstr += strTxt;
  559. if (m_Backup.Check(1))
  560. *cstr += SZ_CHECKED;
  561. AfxFormatString1(strTxt, IDS_HTM_RADIO2B, m_api->SzcResult());
  562. *cstr += strTxt;
  563. }
  564. AfxFormatString2(strTxt, IDS_HTM_RADIO2A, szIdh, SZ_FAILED);
  565. if (m_api->BNodePropItemStr(H_ST_AB_TXT_STR, 0))
  566. {
  567. *cstr += strTxt;
  568. if (m_Backup.Check(0))
  569. *cstr += SZ_CHECKED;
  570. AfxFormatString1(strTxt, IDS_HTM_RADIO2B, m_api->SzcResult());
  571. *cstr += strTxt;
  572. }
  573. AfxFormatString2(strTxt, IDS_HTM_RADIO2A, szIdh, SZ_UNKNOWN);
  574. if (m_api->BNodePropItemStr(H_ST_UKN_TXT_STR, 0))
  575. {
  576. *cstr += strTxt;
  577. if (m_Backup.Check(102))
  578. *cstr += SZ_CHECKED;
  579. AfxFormatString1(strTxt, IDS_HTM_RADIO2B, m_api->SzcResult());
  580. *cstr += strTxt;
  581. }
  582. return;
  583. }
  584. VOID CInfer::GetInfoRadios(LPCTSTR szIdh, CString *cstr)
  585. {
  586. CString strTxt;
  587. AfxFormatString2(strTxt, IDS_HTM_RADIO2A, szIdh, SZ_YES);
  588. if (m_api->BNodePropItemStr(H_ST_NORM_TXT_STR, 0))
  589. {
  590. *cstr += strTxt;
  591. if (m_Backup.Check(0))
  592. *cstr += SZ_CHECKED;
  593. AfxFormatString1(strTxt, IDS_HTM_RADIO2B, m_api->SzcResult());
  594. *cstr += strTxt;
  595. }
  596. AfxFormatString2(strTxt, IDS_HTM_RADIO2A, szIdh, SZ_NO);
  597. if (m_api->BNodePropItemStr(H_ST_AB_TXT_STR, 0))
  598. {
  599. *cstr += strTxt;
  600. if (m_Backup.Check(1))
  601. *cstr += SZ_CHECKED;
  602. AfxFormatString1(strTxt, IDS_HTM_RADIO2B, m_api->SzcResult());
  603. *cstr += strTxt;
  604. }
  605. AfxFormatString2(strTxt, IDS_HTM_RADIO2A, szIdh, SZ_UNKNOWN);
  606. if (m_api->BNodePropItemStr(H_ST_UKN_TXT_STR, 0))
  607. {
  608. *cstr += strTxt;
  609. if (m_Backup.Check(102))
  610. *cstr += SZ_CHECKED;
  611. AfxFormatString1(strTxt, IDS_HTM_RADIO2B, m_api->SzcResult());
  612. *cstr += strTxt;
  613. }
  614. return;
  615. }
  616. // GetPropItemStrs can not be used with the radio buttons.
  617. // GetPropItemStrs should be used every where.
  618. bool CInfer::GetNetPropItemStrs(TSZC item, UINT Res, CString *cstr)
  619. {
  620. bool ret = false;
  621. CString strTxt;
  622. int x = 0;
  623. while (m_api->BNetPropItemStr(item, x))
  624. {
  625. AfxFormatString1(strTxt, Res, m_api->SzcResult());
  626. *cstr += strTxt;
  627. ret = true;
  628. x++;
  629. }
  630. return ret;
  631. }
  632. bool CInfer::GetNodePropItemStrs(TSZC item, UINT Res, CString *cstr)
  633. {
  634. bool ret = false;
  635. CString strTxt;
  636. int x = 0;
  637. while (m_api->BNodePropItemStr(item, x))
  638. {
  639. AfxFormatString1(strTxt, Res, m_api->SzcResult());
  640. *cstr += strTxt;
  641. ret = true;
  642. x++;
  643. }
  644. return ret;
  645. }
  646. VOID CInfer::GetByeMsg(LPCTSTR szIdh, CString *cstr)
  647. {
  648. CString strTxt;
  649. CString strBack;
  650. CString strStart;
  651. AfxFormatString2(strTxt, IDS_HTM_IDH3, szIdh, _T("IDH_BYE"));
  652. *cstr += strTxt;
  653. GetNetPropItemStrs(HX_BYE_HD_STR, IDS_HTM_HEADER3, cstr);
  654. GetNetPropItemStrs(HX_BYE_TXT_STR, IDS_HTM_BODY1, cstr);
  655. GetBackButton(strBack);
  656. GetStartButton(strStart);
  657. AfxFormatString2(strTxt, IDS_HTM_EN_BYE_MSG, (LPCTSTR) strBack, (LPCTSTR) strStart);
  658. *cstr += strTxt;
  659. return;
  660. }
  661. VOID CInfer::GetFailMsg(LPCTSTR szIdh, CString *cstr)
  662. {
  663. CString strTxt;
  664. CString strBack;
  665. CString strStart;
  666. bool bSniffedAOK = false; // set true in the case where we got here directly by
  667. // sniffing (showing nothing but the problem page, or
  668. // not even that). $BUG Unfortunately, we haven't yet got
  669. // an algorithm to set this.
  670. AfxFormatString2(strTxt, IDS_HTM_IDH4, szIdh, _T("IDH_FAIL"));
  671. *cstr += strTxt;
  672. if (bSniffedAOK)
  673. {
  674. if (!GetNetPropItemStrs(HX_SNIFF_AOK_HD_STR, IDS_HTM_HEADER4, cstr))
  675. GetNetPropItemStrs(HX_FAIL_HD_STR, IDS_HTM_HEADER4, cstr);
  676. if (!GetNetPropItemStrs(HX_SNIFF_AOK_TXT_STR, IDS_HTM_BODY2, cstr))
  677. GetNetPropItemStrs(HX_FAIL_TXT_STR, IDS_HTM_BODY2, cstr);
  678. }
  679. else
  680. {
  681. GetNetPropItemStrs(HX_FAIL_HD_STR, IDS_HTM_HEADER4, cstr);
  682. GetNetPropItemStrs(HX_FAIL_TXT_STR, IDS_HTM_BODY2, cstr);
  683. }
  684. GetBackButton(strBack);
  685. GetStartButton(strStart);
  686. AfxFormatString2(strTxt, IDS_HTM_BACK_START, (LPCTSTR) strBack, (LPCTSTR) strStart);
  687. *cstr += strTxt;
  688. return;
  689. }
  690. VOID CInfer::GetServiceMsg(LPCTSTR szIdh, CString *cstr)
  691. {
  692. CString strTxt;
  693. CString strBack;
  694. CString strNext;
  695. CString strStart;
  696. AfxFormatString2(strTxt, IDS_HTM_IDH5, szIdh, _T("SERVICE"));
  697. *cstr += strTxt;
  698. GetNetPropItemStrs(HX_SER_HD_STR, IDS_HTM_HEADER5, cstr);
  699. GetNetPropItemStrs(HX_SER_TXT_STR, IDS_HTM_BODY3, cstr);
  700. /*
  701. strTxt.LoadString(IDS_HTM_ST_LIST2);
  702. *cstr += strTxt;
  703. AfxFormatString2(strTxt, IDS_HTM_RADIO2A, TRY_TS_AT_MICROSOFT_SZ, SZ_MICRO);
  704. if (m_api->BNetPropItemStr(HX_SER_MS_STR, 0))
  705. {
  706. *cstr += strTxt;
  707. AfxFormatString1(strTxt, IDS_HTM_RADIO2B, m_api->SzcResult());
  708. *cstr += strTxt;
  709. }
  710. GetStd3ButtonEnList(cstr, true, true, true);
  711. */
  712. GetBackButton(strBack);
  713. GetStartButton(strStart);
  714. AfxFormatString2(strTxt, IDS_HTM_BACK_START, (LPCTSTR) strBack, (LPCTSTR) strStart);
  715. *cstr += strTxt;
  716. return;
  717. }
  718. VOID CInfer::GetSkippedNodesMsg(LPCTSTR szIdh, CString *cstr)
  719. {
  720. CString strTxt;
  721. AfxFormatString2(strTxt, IDS_HTM_IDH5, szIdh, _T("SERVICE"));
  722. *cstr += strTxt;
  723. GetNetPropItemStrs(HX_SKIP_HD_STR, IDS_HTM_HEADER5, cstr);
  724. GetNetPropItemStrs(HX_SKIP_TXT_STR, IDS_HTM_BODY3, cstr);
  725. strTxt.LoadString(IDS_HTM_ST_LIST2);
  726. *cstr += strTxt;
  727. AfxFormatString2(strTxt, IDS_HTM_RADIO2A, TRY_TS_AT_MICROSOFT_SZ, SZ_ANY);
  728. if (m_api->BNetPropItemStr(HX_SKIP_SK_STR, 0))
  729. { // Did I skip something?
  730. *cstr += strTxt;
  731. AfxFormatString1(strTxt, IDS_HTM_RADIO2B, m_api->SzcResult());
  732. *cstr += strTxt;
  733. }
  734. GetStd3ButtonEnList(cstr, true, true, true);
  735. return;
  736. }
  737. VOID CInfer::GetImpossibleNodesMsg(LPCTSTR szIdh, CString *cstr)
  738. {
  739. CString strTxt;
  740. CString strBack;
  741. CString strStart;
  742. AfxFormatString2(strTxt, IDS_HTM_IDH5, szIdh, _T("SERVICE"));
  743. *cstr += strTxt;
  744. GetNetPropItemStrs(HX_IMP_HD_STR, IDS_HTM_HEADER5, cstr);
  745. GetNetPropItemStrs(HX_IMP_TXT_STR, IDS_HTM_BODY3, cstr);
  746. GetBackButton(strBack);
  747. GetStartButton(strStart);
  748. AfxFormatString2(strTxt, IDS_EN_IMP, (LPCTSTR) strBack, (LPCTSTR) strStart);
  749. *cstr += strTxt;
  750. return;
  751. }
  752. VOID CInfer::GetIdhPage(IDH idh, CString *cstr)
  753. {
  754. CString strTxt;
  755. CString strIdh;
  756. CString str;
  757. str.Format(_T("%d"), idh);
  758. if (m_api->BNodeSetCurrent(idh - idhFirst))
  759. {
  760. m_api->NodeSymName();
  761. strIdh = m_api->SzcResult();
  762. }
  763. else
  764. strIdh = _T("");
  765. if (IDH_BYE == idh)
  766. {
  767. strIdh.Format(_T("%d"), idh);
  768. GetByeMsg((LPCTSTR) strIdh, cstr);
  769. }
  770. else if (IDH_FAIL == idh)
  771. {
  772. strIdh.Format(_T("%d"), idh);
  773. GetFailMsg((LPCTSTR) strIdh, cstr);
  774. }
  775. else if ((nidService + idhFirst)== idh)
  776. {
  777. strIdh.Format(_T("%d"), idh);
  778. GetServiceMsg((LPCTSTR) strIdh, cstr);
  779. }
  780. else
  781. {
  782. // normal node
  783. AfxFormatString2(strTxt, IDS_HTM_IDH2, (LPCTSTR) strIdh, (LPCTSTR) str);
  784. *cstr += strTxt;
  785. if (GetForcedRecommendation() + idhFirst == idh)
  786. GetNodePropItemStrs(H_NODE_DCT_STR, IDS_HTM_HEADER2, cstr);
  787. else
  788. GetNodePropItemStrs(H_NODE_HD_STR, IDS_HTM_HEADER2, cstr);
  789. GetNodePropItemStrs(H_NODE_TXT_STR, IDS_HTM_TEXT1, cstr);
  790. strTxt.LoadString(IDS_HTM_ST_LIST2);
  791. *cstr += strTxt;
  792. if (GetForcedRecommendation() + idhFirst != idh)
  793. {
  794. ESTDLBL lbl = m_api->ELblNode();
  795. if (ESTDLBL_fixobs == lbl || ESTDLBL_fixunobs == lbl || ESTDLBL_unfix == lbl)
  796. GetFixRadios((LPCTSTR) strIdh, cstr);
  797. else if (ESTDLBL_info == lbl)
  798. GetInfoRadios((LPCTSTR) strIdh, cstr);
  799. }
  800. // We only want to show a BACK button if at least one node has been set or skipped.
  801. // This does not include nodes initiallly set on instructions from TSLaunchServ:
  802. // the whole point is to avoid stepping "back" into things that were set by
  803. // the launch server rather than by the user.
  804. {
  805. //DEBUG
  806. //AfxDebugBreak();
  807. int testNowSet = m_api->StatesNowSet();
  808. int testStatesFromServ = m_api->StatesFromServ();
  809. }
  810. // Suppress back button if we launched to a network with a problem node and
  811. // no further nodes have been set. It's not the problem page, but (as far as user
  812. // is concerned) it's the first page.
  813. bool bIncludeBackButton =
  814. m_api->StatesNowSet() > m_api->StatesFromServ() || m_cnidSkip > 0;
  815. // We would like to suppress the back button in the similar scenario where
  816. // sniffing takes us past the first recommendation. For example:
  817. // Launcher specifies problem.
  818. // First recommendation for that problem is sniffed as "normal" (state = 0)
  819. // Now the first node we show is even deeper into the chain.
  820. bIncludeBackButton = bIncludeBackButton &&
  821. (m_api->IsRunWithKnownProblem() ?
  822. (m_api->GetCountRecommendedNodes() >
  823. m_api->GetCountSniffedRecommendedNodes() + 1/*this is for the problem we've started with*/) :
  824. 1);
  825. // We supress back button ALWAYS when we have sniffed foxobs node that worked
  826. // we can be either on the problem page where we do not need back button
  827. // or on problem resolution page from where we never go back
  828. bIncludeBackButton = bIncludeBackButton &&
  829. m_api->GetSniffedFixobsThatWorked() == SNIFF_INVALID_NODE_ID;
  830. // We do not want to have a NEXT button when we are on the problem resolution page
  831. bool bIncludeNextButton = (GetForcedRecommendation() + idhFirst) != idh;
  832. GetStd3ButtonEnList(cstr, bIncludeBackButton, bIncludeNextButton, true);
  833. }
  834. return;
  835. }
  836. //
  837. //
  838. BOOL CInfer::FSkip(NID nid) const
  839. {
  840. for (UINT inid = 0; inid < m_cnidSkip; inid++)
  841. {
  842. if (m_rgnidSkip[inid] == nid)
  843. {
  844. return TRUE;
  845. }
  846. }
  847. return FALSE;
  848. }
  849. void CInfer::BackUp(int nid, int state)
  850. {
  851. m_Backup.SetState(nid, state); // This sets the radio button.
  852. // Is nid in the skip list?
  853. for (UINT inid = 0; inid < m_cnidSkip; inid++)
  854. {
  855. if (m_rgnidSkip[inid] == (unsigned) nid)
  856. {
  857. // Remove nid from the skip list.
  858. while(inid < (m_cnidSkip - 1))
  859. {
  860. m_rgnidSkip[inid] = m_rgnidSkip[inid + 1];
  861. inid++;
  862. }
  863. m_rgnidSkip[inid] = NULL;
  864. m_cnidSkip--;
  865. }
  866. }
  867. // if (m_cnidSkip < 0)
  868. // m_cnidSkip = 0;
  869. return;
  870. }
  871. //
  872. //
  873. VOID CInfer::AddSkip(NID nid)
  874. {
  875. if (!FSkip(nid))
  876. {
  877. if (m_cnidSkip < cnidMacSkip)
  878. {
  879. m_rgnidSkip[m_cnidSkip++] = nid;
  880. }
  881. }
  882. }
  883. VOID CInfer::RemoveSkips()
  884. {
  885. for(UINT x = 0; x < m_cnidSkip; x++)
  886. m_rgnidSkip[x] = NULL;
  887. m_cnidSkip = 0;
  888. return;
  889. }
  890. //
  891. //
  892. VOID CInfer::PrintMessage(TSZC szcFormat, ...) const
  893. {
  894. va_list ptr;
  895. TCHAR formatbuf[1024];
  896. if (szcFormat) {
  897. _tcscpy(formatbuf,_T("<H4>"));
  898. va_start(ptr,szcFormat);
  899. _vstprintf(&formatbuf[4],szcFormat,ptr);
  900. va_end(ptr);
  901. _tcscat(formatbuf,_T("</H4>"));
  902. *m_pCtxt += formatbuf;
  903. }
  904. }
  905. //
  906. //
  907. VOID CInfer::PrintString(TSZC szcFormat, ...) const
  908. {
  909. va_list ptr;
  910. TCHAR formatbuf[1024];
  911. if (szcFormat) {
  912. va_start(ptr,szcFormat);
  913. _vstprintf(formatbuf,szcFormat,ptr);
  914. va_end(ptr);
  915. *m_pCtxt += formatbuf;
  916. }
  917. }
  918. // this data is now in CSniffedInfoContainer
  919. /*
  920. // This allows a higher level to say "don't go to the belief network for a recommendation,
  921. // I already know what to recommend." Used in conjunction with a sniffer.
  922. VOID CInfer::ForceRecommendation(IDH idh)
  923. {
  924. m_idhSniffedRecommendation= idh;
  925. }
  926. */
  927. // Associate a state with a node.
  928. // INPUT idh - either (node ID + 1000) or one
  929. // of the special values IDH_BYE, IDH_FAIL, (nidService + 1000)
  930. // INPUT ist - index of a state for that node
  931. // RETURNS >>> document?.
  932. BOOL CInfer::FSetNodeOfIdh(IDH idh, IST ist)
  933. {
  934. if (ist == 101)
  935. {
  936. m_fDone = TRUE;
  937. return TRUE;
  938. }
  939. if (ist == 103)
  940. {
  941. m_ishowService++;
  942. return TRUE;
  943. }
  944. if (idh < idhFirst)
  945. return TRUE;
  946. if (idh > m_acnid + idhFirst && idh != IDH_SERVICE)
  947. return TRUE;
  948. if (ist == 102)
  949. { // "don't want to do this now"
  950. AddSkip(idh - idhFirst);
  951. SaveNID(idh - idhFirst);
  952. return TRUE;
  953. }
  954. if (idh == m_api->GetProblemAsk()) {
  955. // get data for problem
  956. IDH *idarray = NULL;
  957. NID nidProblem = nidNil;
  958. UINT iproblem = 0;
  959. UINT inid;
  960. UINT count = m_api->GetProblemArray(&idarray);
  961. for (inid = 0; inid < count; inid++) {
  962. if (ist == idarray[inid]) {
  963. nidProblem = ist - idhFirst;
  964. iproblem = ist;
  965. if (!m_api->NodeSet(idarray[inid] - idhFirst, ist == idarray[inid] ? 1 : 0,
  966. m_Backup.InReverse()))
  967. return FALSE;
  968. break;
  969. }
  970. }
  971. if (nidProblem == nidNil) {
  972. m_idhQuestion = IDH_SERVICE;
  973. return TRUE;
  974. }
  975. m_api->BNodeSetCurrent(nidProblem);
  976. m_api->NodeFullName();
  977. _stprintf(m_problem, _T("%s<INPUT TYPE=HIDDEN NAME=%u VALUE=%u>"), m_api->SzcResult(), idh, iproblem);
  978. m_firstNid = idh - idhFirst;
  979. m_firstSet = iproblem;
  980. return TRUE;
  981. }
  982. NID nid = idh - idhFirst;
  983. if (nid != nidService)
  984. if (!m_api->NodeSet(nid, ist, m_Backup.InReverse()))
  985. return FALSE;
  986. SaveNID(nid); // save this node id so we can print it at the end
  987. return TRUE;
  988. }
  989. //
  990. //
  991. void CInfer::SaveNID(UINT nid)
  992. {
  993. m_rgnid[m_max_rec] = nid;
  994. m_max_rec++;
  995. }
  996. //
  997. //
  998. void CInfer::WriteResult(UINT name, UINT value, BOOL bSet, TSZC szctype, CString *cstr) const
  999. {
  1000. TCHAR ctemp[1024];
  1001. TCHAR* szFmtInput = _T("<INPUT TYPE=RADIO NAME=%u VALUE=%u%s>%-16s ");
  1002. _stprintf(ctemp, szFmtInput,
  1003. name, value, bSet ? _T(" CHECKED") : _T(""), szctype);
  1004. *cstr += ctemp;
  1005. }
  1006. //
  1007. //
  1008. int CInfer::Finish(CString *cstr)
  1009. {
  1010. CString strTxt;
  1011. if (m_fDone)
  1012. {
  1013. GetIdhPage(IDH_BYE, cstr);
  1014. // Reset the done flag so that the Previous button will work correctly.
  1015. m_fDone = FALSE;
  1016. return FALSE;
  1017. }
  1018. if (m_idhQuestion != 0)
  1019. {
  1020. GetIdhPage(m_idhQuestion, cstr);
  1021. return FALSE;
  1022. }
  1023. if (m_api->BImpossible())
  1024. {
  1025. GetImpossibleNodesMsg(_T("Impossible"), cstr);
  1026. return FALSE;
  1027. }
  1028. //
  1029. // we've come down to ask recommendations
  1030. //
  1031. int iRecommendRes = m_api->GTSGetRecommendations(m_cnid, m_question_rgnid);
  1032. return iRecommendRes;
  1033. }
  1034. // ResetSevice is called when the start button is pressed. CTSHOOTCtrl::ProblemPage()
  1035. void CInfer::ResetService()
  1036. {
  1037. m_ishowService = 0;
  1038. m_cnidSkip = 0;
  1039. m_cnid = 0;
  1040. return;
  1041. }
  1042. //
  1043. //
  1044. void CInfer::SetType(LPCTSTR type)
  1045. {
  1046. _stprintf(m_tstype, _T("%s"),type);
  1047. }
  1048. //
  1049. //
  1050. void CInfer::LoadTShooters(HKEY hRegKey)
  1051. {
  1052. long lRet;
  1053. int x;
  1054. HKEY hkeyShooter;
  1055. TShooter tShooter;
  1056. TShooter tsTemp;
  1057. CString strKeyName = _T("");
  1058. CString strKeyPath = _T("");
  1059. CString strTSPath = _T("");
  1060. CString strData = _T("");
  1061. DWORD dwIndex = 0;
  1062. DWORD dwKeySize = MAXBUF;
  1063. FILETIME fileTime;
  1064. DWORD dwDataSize = MAXBUF;
  1065. DWORD dwType = REG_SZ;
  1066. m_cShooters = 0;
  1067. m_iShooter = 0;
  1068. strKeyPath.Format(_T("%s\\%s"), TSREGKEY_MAIN, REGSZ_TSTYPES);
  1069. while (ERROR_SUCCESS ==
  1070. (lRet = RegEnumKeyEx(hRegKey,
  1071. dwIndex, strKeyName.GetBufferSetLength(MAXBUF),
  1072. &dwKeySize, NULL,
  1073. NULL, NULL,
  1074. &fileTime)))
  1075. {
  1076. strKeyName.ReleaseBuffer();
  1077. strTSPath.Format(_T("%s\\%s"),(LPCTSTR) strKeyPath, (LPCTSTR) strKeyName);
  1078. if ((lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1079. (LPCTSTR) strTSPath,
  1080. NULL,
  1081. KEY_READ,
  1082. &hkeyShooter)) == ERROR_SUCCESS)
  1083. {
  1084. if ((lRet = RegQueryValueEx(hkeyShooter,
  1085. FRIENDLY_NAME,
  1086. 0,
  1087. &dwType,
  1088. (LPBYTE) strData.GetBufferSetLength(MAXBUF),
  1089. &dwDataSize)) == ERROR_SUCCESS)
  1090. {
  1091. strData.ReleaseBuffer();
  1092. m_cShooters++;
  1093. _tcsncpy(tShooter.m_szName, (LPCTSTR) strKeyName, strKeyName.GetLength() + 1);
  1094. _tcsncpy(tShooter.m_szDisplayName, (LPCTSTR) strData, strData.GetLength() + 1);
  1095. x = (int)m_aShooters.GetSize();
  1096. while (x > 0)
  1097. {
  1098. x--;
  1099. tsTemp = m_aShooters.GetAt(x);
  1100. if (_tcscmp(tsTemp.m_szDisplayName, tShooter.m_szDisplayName) < 0)
  1101. {
  1102. x++;
  1103. break;
  1104. }
  1105. }
  1106. m_aShooters.InsertAt(x, tShooter);
  1107. }
  1108. RegCloseKey(hkeyShooter);
  1109. }
  1110. dwIndex++;
  1111. dwKeySize = MAXBUF;
  1112. dwDataSize = MAXBUF;
  1113. dwType = REG_SZ;
  1114. strKeyName = _T("");
  1115. strData = _T("");
  1116. }
  1117. ASSERT(ERROR_NO_MORE_ITEMS == lRet);
  1118. return;
  1119. }
  1120. //
  1121. //
  1122. int CInfer::GetForcedRecommendation()
  1123. {
  1124. return m_api->GetSniffedFixobsThatWorked();
  1125. }
  1126.