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.

1348 lines
34 KiB

  1. // MODULE: TSHOOTCTL.CPP
  2. //
  3. // PURPOSE: Interface for the componet.
  4. //
  5. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  6. //
  7. // COMPANY: Saltmine Creative, Inc. (206)-633-4743 [email protected]
  8. //
  9. // AUTHOR: Roman Mach
  10. //
  11. // ORIGINAL DATE: 6/4/96
  12. //
  13. // NOTES:
  14. // 1. Based on Print Troubleshooter DLL.
  15. // 2. Richard Meadows wrote the RunQuery, BackUp, Problem Page and
  16. // PreLoadURL functions.
  17. //
  18. // Version Date By Comments
  19. //--------------------------------------------------------------------
  20. // V0.1 - RM Original
  21. // V0.3 04/09/98 JM/OK+ Local Version for NT5
  22. //
  23. #include "stdafx.h"
  24. #include "ErrorEnums.h"
  25. #include "cathelp.h"
  26. #include "TSHOOT.h"
  27. #include "time.h"
  28. #include "apgts.h"
  29. #include "ErrorEnums.h"
  30. #include "BasicException.h"
  31. #include "apgtsfst.h"
  32. #include "ErrorEnums.h"
  33. #include "CabUnCompress.h"
  34. #include "bnts.h"
  35. #include "BackupInfo.h"
  36. #include "cachegen.h"
  37. #include "apgtsinf.h"
  38. #include "apgtscmd.h"
  39. #include "apgtshtx.h"
  40. #include "apgtscls.h"
  41. #include "OcxGlobals.h"
  42. class CTSHOOTCtrl;
  43. #include "dnldlist.h"
  44. #include "download.h"
  45. #include "TSHOOTCtl.h"
  46. #include "TSHOOTPpg.h"
  47. #include "Functions.h"
  48. #include "ErrorEnums.h"
  49. #include "BasicException.h"
  50. #include "HttpQueryException.h"
  51. #include <stdlib.h>
  52. #include "LaunchServ.h"
  53. #include "LaunchServ_i.c"
  54. // >>> test
  55. #include "fstream.h"
  56. #ifdef _DEBUG
  57. #define new DEBUG_NEW
  58. #undef THIS_FILE
  59. static char THIS_FILE[] = __FILE__;
  60. #endif
  61. IMPLEMENT_DYNCREATE(CTSHOOTCtrl, COleControl)
  62. /////////////////////////////////////////////////////////////////////////////
  63. // Message map
  64. BEGIN_MESSAGE_MAP(CTSHOOTCtrl, COleControl)
  65. //{{AFX_MSG_MAP(CTSHOOTCtrl)
  66. // NOTE - ClassWizard will add and remove message map entries
  67. // DO NOT EDIT what you see in these blocks of generated code !
  68. //}}AFX_MSG_MAP
  69. ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
  70. END_MESSAGE_MAP()
  71. /////////////////////////////////////////////////////////////////////////////
  72. // Dispatch map
  73. BEGIN_DISPATCH_MAP(CTSHOOTCtrl, COleControl)
  74. //{{AFX_DISPATCH_MAP(CTSHOOTCtrl)
  75. DISP_PROPERTY_NOTIFY(CTSHOOTCtrl, "DownloadURL", m_downloadURL, OnDownloadURLChanged, VT_BSTR)
  76. DISP_PROPERTY_NOTIFY(CTSHOOTCtrl, "DownloadListFilename", m_downloadListFilename, OnDownloadListFilenameChanged, VT_BSTR)
  77. DISP_FUNCTION(CTSHOOTCtrl, "RunQuery", RunQuery, VT_BSTR, VTS_VARIANT VTS_VARIANT VTS_I2)
  78. DISP_FUNCTION(CTSHOOTCtrl, "SetSniffResult", SetSniffResult, VT_BOOL, VTS_VARIANT VTS_VARIANT)
  79. DISP_FUNCTION(CTSHOOTCtrl, "GetExtendedError", GetExtendedError, VT_I4, VTS_NONE)
  80. DISP_FUNCTION(CTSHOOTCtrl, "GetCurrentFriendlyDownload", GetCurrentFriendlyDownload, VT_BSTR, VTS_NONE)
  81. DISP_FUNCTION(CTSHOOTCtrl, "GetCurrentFileDownload", GetCurrentFileDownload, VT_BSTR, VTS_NONE)
  82. DISP_FUNCTION(CTSHOOTCtrl, "DownloadAction", DownloadAction, VT_I4, VTS_I4)
  83. DISP_FUNCTION(CTSHOOTCtrl, "BackUp", BackUp, VT_BSTR, VTS_NONE)
  84. DISP_FUNCTION(CTSHOOTCtrl, "ProblemPage", ProblemPage, VT_BSTR, VTS_NONE)
  85. DISP_FUNCTION(CTSHOOTCtrl, "PreLoadURL", PreLoadURL, VT_BSTR, VTS_BSTR)
  86. DISP_FUNCTION(CTSHOOTCtrl, "Restart", Restart, VT_BSTR, VTS_NONE)
  87. DISP_FUNCTION(CTSHOOTCtrl, "RunQuery2", RunQuery2, VT_BSTR, VTS_BSTR VTS_BSTR VTS_BSTR)
  88. DISP_FUNCTION(CTSHOOTCtrl, "SetPair", SetPair, VT_EMPTY, VTS_BSTR VTS_BSTR)
  89. //}}AFX_DISPATCH_MAP
  90. DISP_FUNCTION_ID(CTSHOOTCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
  91. END_DISPATCH_MAP()
  92. /////////////////////////////////////////////////////////////////////////////
  93. // Event map
  94. BEGIN_EVENT_MAP(CTSHOOTCtrl, COleControl)
  95. //{{AFX_EVENT_MAP(CTSHOOTCtrl)
  96. EVENT_CUSTOM("BindProgress", FireBindProgress, VTS_BSTR VTS_I4 VTS_I4)
  97. EVENT_CUSTOM("BindStatus", FireBindStatus, VTS_I4 VTS_I4 VTS_I4 VTS_BOOL)
  98. EVENT_CUSTOM("Sniffing", FireSniffing, VTS_BSTR VTS_BSTR VTS_BSTR VTS_BSTR)
  99. //}}AFX_EVENT_MAP
  100. END_EVENT_MAP()
  101. /////////////////////////////////////////////////////////////////////////////
  102. // Property pages
  103. // TODO: Add more property pages as needed. Remember to increase the count!
  104. BEGIN_PROPPAGEIDS(CTSHOOTCtrl, 1)
  105. PROPPAGEID(CTSHOOTPropPage::guid)
  106. END_PROPPAGEIDS(CTSHOOTCtrl)
  107. /////////////////////////////////////////////////////////////////////////////
  108. // Initialize class factory and guid
  109. IMPLEMENT_OLECREATE_EX(CTSHOOTCtrl, "TSHOOT.TSHOOTCtrl.1",
  110. 0x4b106874, 0xdd36, 0x11d0, 0x8b, 0x44, 0, 0xa0, 0x24, 0xdd, 0x9e, 0xff)
  111. /////////////////////////////////////////////////////////////////////////////
  112. // Type library ID and version
  113. IMPLEMENT_OLETYPELIB(CTSHOOTCtrl, _tlid, _wVerMajor, _wVerMinor)
  114. /////////////////////////////////////////////////////////////////////////////
  115. // Interface IDs
  116. const IID BASED_CODE IID_DTSHOOT =
  117. { 0x4b106872, 0xdd36, 0x11d0, { 0x8b, 0x44, 0, 0xa0, 0x24, 0xdd, 0x9e, 0xff } };
  118. const IID BASED_CODE IID_DTSHOOTEvents =
  119. { 0x4b106873, 0xdd36, 0x11d0, { 0x8b, 0x44, 0, 0xa0, 0x24, 0xdd, 0x9e, 0xff } };
  120. const CATID CATID_SafeForScripting = {0x7dd95801,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}};
  121. const CATID CATID_SafeForInitializing = {0x7dd95802,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}};
  122. /////////////////////////////////////////////////////////////////////////////
  123. // Control type information
  124. static const DWORD BASED_CODE _dwTSHOOTOleMisc =
  125. OLEMISC_ACTIVATEWHENVISIBLE |
  126. OLEMISC_SETCLIENTSITEFIRST |
  127. OLEMISC_INSIDEOUT |
  128. OLEMISC_CANTLINKINSIDE |
  129. OLEMISC_RECOMPOSEONRESIZE;
  130. IMPLEMENT_OLECTLTYPE(CTSHOOTCtrl, IDS_TSHOOT, _dwTSHOOTOleMisc)
  131. /////////////////////////////////////////////////////////////////////////////
  132. // CTSHOOTCtrl::CTSHOOTCtrlFactory::UpdateRegistry -
  133. // Adds or removes system registry entries for CTSHOOTCtrl
  134. BOOL CTSHOOTCtrl::CTSHOOTCtrlFactory::UpdateRegistry(BOOL bRegister)
  135. {
  136. // TODO: Verify that your control follows apartment-model threading rules.
  137. // Refer to MFC TechNote 64 for more information.
  138. // If your control does not conform to the apartment-model rules, then
  139. // you must modify the code below, changing the 6th parameter from
  140. // afxRegApartmentThreading to 0.
  141. HRESULT hr;
  142. BOOL bRes;
  143. if (bRegister)
  144. {
  145. bRes = AfxOleRegisterControlClass(
  146. AfxGetInstanceHandle(),
  147. m_clsid,
  148. m_lpszProgID,
  149. IDS_TSHOOT,
  150. IDB_TSHOOT,
  151. afxRegApartmentThreading,
  152. _dwTSHOOTOleMisc,
  153. _tlid,
  154. _wVerMajor,
  155. _wVerMinor);
  156. hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls that are safely scriptable");
  157. ASSERT(SUCCEEDED(hr));
  158. hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data");
  159. ASSERT(SUCCEEDED(hr));
  160. hr = RegisterCLSIDInCategory(m_clsid, CATID_SafeForScripting);
  161. ASSERT(SUCCEEDED(hr));
  162. hr = RegisterCLSIDInCategory(m_clsid, CATID_SafeForInitializing);
  163. ASSERT(SUCCEEDED(hr));
  164. }
  165. else
  166. {
  167. hr = UnRegisterCLSIDInCategory(m_clsid, CATID_SafeForScripting);
  168. ASSERT(SUCCEEDED(hr));
  169. hr = UnRegisterCLSIDInCategory(m_clsid, CATID_SafeForInitializing);
  170. ASSERT(SUCCEEDED(hr));
  171. bRes = AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  172. }
  173. return bRes;
  174. }
  175. /////////////////////////////////////////////////////////////////////////////
  176. // CTSHOOTCtrl::CTSHOOTCtrl - Constructor
  177. CTSHOOTCtrl::CTSHOOTCtrl()
  178. {
  179. InitializeIIDs(&IID_DTSHOOT, &IID_DTSHOOTEvents);
  180. // TODO: Initialize your control's instance data here.
  181. m_strCurShooter = _T("");
  182. m_download = NULL;
  183. m_bComplete = TRUE;
  184. m_dwExtendedErr = LTSC_OK;
  185. m_pSniffedContainer = NULL;
  186. }
  187. /////////////////////////////////////////////////////////////////////////////
  188. // CTSHOOTCtrl::~CTSHOOTCtrl - Destructor
  189. CTSHOOTCtrl::~CTSHOOTCtrl()
  190. {
  191. // TODO: Cleanup your control's instance data here.
  192. }
  193. /////////////////////////////////////////////////////////////////////////////
  194. // CTSHOOTCtrl::OnDraw - Drawing function
  195. void CTSHOOTCtrl::OnDraw(
  196. CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
  197. {
  198. // TODO: Replace the following code with your own drawing code.
  199. pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
  200. pdc->Ellipse(rcBounds);
  201. }
  202. /////////////////////////////////////////////////////////////////////////////
  203. // CTSHOOTCtrl::DoPropExchange - Persistence support
  204. void CTSHOOTCtrl::DoPropExchange(CPropExchange* pPX)
  205. {
  206. ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  207. COleControl::DoPropExchange(pPX);
  208. }
  209. /////////////////////////////////////////////////////////////////////////////
  210. // CTSHOOTCtrl::OnResetState - Reset control to default state
  211. void CTSHOOTCtrl::OnResetState()
  212. {
  213. COleControl::OnResetState(); // Resets defaults found in DoPropExchange
  214. // TODO: Reset any other control state here.
  215. }
  216. /////////////////////////////////////////////////////////////////////////////
  217. // CTSHOOTCtrl::AboutBox - Display an "About" box to the user
  218. void CTSHOOTCtrl::AboutBox()
  219. {
  220. CDialog dlgAbout(IDD_ABOUTBOX_TSHOOT);
  221. dlgAbout.DoModal();
  222. }
  223. /////////////////////////////////////////////////////////////////////////////
  224. // CTSHOOTCtrl message handlers
  225. bool CTSHOOTCtrl::SetSniffResult(const VARIANT FAR& varNodeName, const VARIANT FAR& varNodeState)
  226. {
  227. BSTR bstrNodeName = NULL;
  228. int iNodeState = 0;
  229. short sNodeNameLen = 0;
  230. TCHAR* tszNodeName = NULL;
  231. bool ret = true;
  232. // >>> test
  233. #ifdef _DEBUG
  234. // AfxDebugBreak();
  235. #endif
  236. if (VT_BYREF == (VT_BYREF & varNodeName.vt) && // data type is VT_VARIANT | VT_BYREF
  237. VT_VARIANT == (VT_VARIANT & varNodeName.vt) // this means that data in VB script was passed as a variable
  238. )
  239. {
  240. bstrNodeName = varNodeName.pvarVal->bstrVal;
  241. }
  242. else
  243. {
  244. if (VT_BSTR == (VT_BSTR & varNodeName.vt)) // data is of VT_BSTR type
  245. // this means that data in VB script was passed as a constant
  246. bstrNodeName = varNodeName.bstrVal;
  247. else
  248. return false;
  249. }
  250. if (VT_BYREF == (VT_BYREF & varNodeState.vt) && // data type is VT_VARIANT | VT_BYREF
  251. VT_VARIANT == (VT_VARIANT & varNodeState.vt) // this means that data in VB script was passed as a variable
  252. )
  253. {
  254. iNodeState = varNodeState.pvarVal->iVal;
  255. }
  256. else
  257. {
  258. if (VT_I2 == (VT_I2 & varNodeState.vt)) // data is of VT_I2 type
  259. // this means that data in VB script was passed as a constant
  260. iNodeState = varNodeState.iVal;
  261. else
  262. return false;
  263. }
  264. sNodeNameLen = (short)::SysStringLen(bstrNodeName);
  265. tszNodeName = new TCHAR[sNodeNameLen+1];
  266. tszNodeName[sNodeNameLen] = 0;
  267. ::BSTRToTCHAR(tszNodeName, bstrNodeName, sNodeNameLen);
  268. //
  269. // implement set node state functionality here
  270. //
  271. if (m_pSniffedContainer)
  272. {
  273. ret = m_pSniffedContainer->AddNode(tszNodeName, iNodeState);
  274. }
  275. else
  276. {
  277. MessageBox(_T("Sniffed data will be lost!"));
  278. ret = false;
  279. }
  280. //
  281. delete [] tszNodeName;
  282. return ret;
  283. }
  284. BSTR CTSHOOTCtrl::RunQuery(const VARIANT FAR& varCmds, const VARIANT FAR& varVals, short size)
  285. {
  286. CString strCmd1;
  287. CString strTxt;
  288. CString strResult = _T("");
  289. try
  290. {
  291. HMODULE hModule = AfxGetInstanceHandle();
  292. ASSERT(INVALID_HANDLE_VALUE != hModule);
  293. m_httpQuery.Initialize(varCmds, varVals, size);
  294. if (m_httpQuery.GetFirstCmd() == C_ASK_LIBRARY)
  295. {
  296. // Added to support launching by the TS Launcher.
  297. // Get an ILaunchTS interface.
  298. HRESULT hRes;
  299. DWORD dwResult;
  300. ILaunchTS *pILaunchTS = NULL;
  301. CLSID clsidLaunchTS = CLSID_LaunchTS;
  302. IID iidLaunchTS = IID_ILaunchTS;
  303. // Get an interface on the launch server
  304. hRes = CoCreateInstance(clsidLaunchTS, NULL,
  305. CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER | CLSCTX_INPROC_SERVER,
  306. iidLaunchTS, (void **) &pILaunchTS);
  307. if (FAILED(hRes))
  308. {
  309. m_dwExtendedErr = TSERR_LIB_STATE_INFO;
  310. strResult = _T("LaunchServ interface not found.");
  311. return strResult.AllocSysString();
  312. }
  313. // Get all of the query values.
  314. hRes = pILaunchTS->GetShooterStates(&dwResult);
  315. if (FAILED(hRes))
  316. {
  317. m_dwExtendedErr = dwResult;
  318. strResult.Format(_T("<html>GetShooterStates Failed. %ld</html>"), dwResult);
  319. pILaunchTS->Release();
  320. return strResult.AllocSysString();
  321. }
  322. // Run the query.
  323. OLECHAR *poleShooter;
  324. hRes = pILaunchTS->GetTroubleShooter(&poleShooter);
  325. if (FAILED(hRes))
  326. {
  327. m_dwExtendedErr = TSERR_LIB_STATE_INFO;
  328. strResult = _T("<html>GetTroubleShooter Failed. </html>");
  329. pILaunchTS->Release();
  330. return strResult.AllocSysString();
  331. }
  332. m_strCurShooter = poleShooter;
  333. // Ignoring, for now, any other information we may get from the launch server
  334. // (e.g. problem node) set up m_httpQuery and other things as if we just had
  335. // a request for this troubleshooting belief network.
  336. m_httpQuery.SetFirst(CString(C_TYPE), m_strCurShooter);
  337. SysFreeString(poleShooter);
  338. m_Conf.Initialize(hModule, (LPCTSTR) m_strCurShooter
  339. ); // CDBLoadConfiguration
  340. m_apgts.Initialize( m_Conf.GetAPI(), // APGTSContext
  341. &m_Conf,
  342. &m_httpQuery);
  343. m_apgts.RemoveSkips();
  344. m_Conf.GetAPI()->api.pAPI->SetHttpQuery(&m_httpQuery);
  345. // sniffing
  346. m_Conf.GetAPI()->api.pAPI->ReadTheDscModel();
  347. m_pSniffedContainer = m_Conf.GetAPI()->api.pAPI;
  348. m_httpQuery.FinishInitFromServ(m_Conf.GetAPI()->api.pAPI, pILaunchTS);
  349. FireSniffing(m_httpQuery.GetMachine(),
  350. m_httpQuery.GetPNPDevice(),
  351. m_httpQuery.GetDeviceInstance(),
  352. m_httpQuery.GetGuidClass());
  353. pILaunchTS->Release();
  354. pILaunchTS = NULL;
  355. m_httpQuery.SetStackDirection();
  356. m_Conf.SetValues(m_httpQuery);
  357. m_apgts.ClearBackup();
  358. m_Conf.GetAPI()->api.pAPI->SetReverse(false);
  359. m_apgts.DoContent(&m_httpQuery);
  360. // now add sniffed nodes that were automatically traversed
  361. // to the stack of navigated nodes - UGLY
  362. m_httpQuery.PushNodesLastSniffed(m_Conf.GetAPI()->api.pAPI->GetArrLastSniffed());
  363. // Now that we've done all the processing render the appropriate page.
  364. // This is the first page the user sees when launching a torubleshooter.
  365. m_apgts.RenderNext(strResult);
  366. m_apgts.Empty();
  367. }
  368. else if (m_httpQuery.GetFirstCmd() == C_SELECT)
  369. { // Unsupported function.
  370. // Returns a page that has all of the trouble shooters.
  371. try
  372. {
  373. CFirstPage firstPage;
  374. CString str = m_httpQuery.GetTroubleShooter();
  375. firstPage.RenderFirst(strResult, str); // Here I am getting an hit file.
  376. }
  377. catch(CBasicException *pExc)
  378. {
  379. m_dwExtendedErr = pExc->m_dwBErr;
  380. strResult = _T("");
  381. delete pExc;
  382. }
  383. }
  384. else
  385. { // Normal operation.
  386. if (m_httpQuery.GetTroubleShooter() != m_strCurShooter)
  387. {
  388. m_strCurShooter = m_httpQuery.GetTroubleShooter();
  389. m_Conf.Initialize(hModule, (LPCTSTR) m_strCurShooter
  390. ); // CDBLoadConfiguration
  391. m_apgts.Initialize( m_Conf.GetAPI(), // APGTSContext
  392. &m_Conf,
  393. &m_httpQuery);
  394. m_apgts.RemoveSkips();
  395. m_Conf.GetAPI()->api.pAPI->SetHttpQuery(&m_httpQuery);
  396. // sniffing
  397. m_Conf.GetAPI()->api.pAPI->ReadTheDscModel();
  398. m_pSniffedContainer = m_Conf.GetAPI()->api.pAPI;
  399. FireSniffing(m_httpQuery.GetMachine(),
  400. m_httpQuery.GetPNPDevice(),
  401. m_httpQuery.GetDeviceInstance(),
  402. m_httpQuery.GetGuidClass());
  403. }
  404. m_httpQuery.FinishInit(m_Conf.GetAPI()->api.pAPI, varCmds, varVals);
  405. m_httpQuery.SetStackDirection();
  406. m_Conf.SetValues(m_httpQuery);
  407. m_apgts.ClearBackup();
  408. m_Conf.GetAPI()->api.pAPI->SetReverse(false);
  409. m_apgts.DoContent(&m_httpQuery);
  410. // now add sniffed nodes that were automatically traversed
  411. // to the stack of navigated nodes - UGLY
  412. m_httpQuery.PushNodesLastSniffed(m_Conf.GetAPI()->api.pAPI->GetArrLastSniffed());
  413. // >>> test
  414. //static int step = 0;
  415. //char name[16] = {0};
  416. //sprintf(name, "next_step%d.htm", ++step);
  417. //ofstream file(name);
  418. m_apgts.RenderNext(strResult);
  419. //file << (LPCTSTR)strResult;
  420. m_apgts.Empty();
  421. }
  422. }
  423. catch(COleException *pOExc)
  424. {
  425. m_dwExtendedErr = (DLSTATTYPES) pOExc->m_sc;
  426. pOExc->Delete();
  427. strResult = _T("");
  428. }
  429. catch(CBasicException *pExc)
  430. {
  431. m_dwExtendedErr = pExc->m_dwBErr;
  432. delete pExc;
  433. strResult = _T("");
  434. }
  435. unsigned short pErrorStr[2] = { NULL, NULL };
  436. if (strResult.GetLength() > 0)
  437. {
  438. return strResult.AllocSysString();
  439. }
  440. else
  441. {
  442. return SysAllocString((unsigned short *) pErrorStr);
  443. }
  444. }
  445. BSTR CTSHOOTCtrl::BackUp()
  446. {
  447. BCache *pApi = m_Conf.GetAPI()->api.pAPI;
  448. CString strResult = _T("");
  449. if (m_httpQuery.BackUp(pApi, &m_apgts))
  450. {
  451. m_Conf.GetAPI()->api.pAPI->SetReverse(true);
  452. m_apgts.DoContent(&m_httpQuery);
  453. m_apgts.RenderNext(strResult);
  454. m_apgts.Empty();
  455. }
  456. else
  457. m_dwExtendedErr = TSERR_AT_START;
  458. return strResult.AllocSysString();
  459. }
  460. // Starter
  461. // Historically (until March '98) this was called when the "Restart button" is pressed.
  462. // However, that assumed we would always want to go clear back to the problem page, which
  463. // is no longer policy now that the Launcher is introduced.
  464. BSTR CTSHOOTCtrl::ProblemPage()
  465. {
  466. BCache *pApi = m_Conf.GetAPI()->api.pAPI;
  467. CString strResult = _T("");
  468. if (m_strCurShooter.GetLength() > 0)
  469. {
  470. m_httpQuery.RemoveNodes(pApi);
  471. m_apgts.DoContent(&m_httpQuery);
  472. m_apgts.RenderNext(strResult);
  473. m_apgts.Empty();
  474. }
  475. else
  476. m_dwExtendedErr = TSERR_NOT_STARTED;
  477. m_apgts.ResetService();
  478. return strResult.AllocSysString();
  479. }
  480. // Called when the "Restart button" is pressed.
  481. // If TS Launcher was not involved, go clear back to the problem page.
  482. // If TS Launcher is involved, go back to the page we launched to, which may or may not
  483. // be the problem page.
  484. BSTR CTSHOOTCtrl::Restart()
  485. {
  486. BCache *pApi = m_Conf.GetAPI()->api.pAPI;
  487. CString strResult;
  488. // >>> test
  489. #ifdef _DEBUG
  490. // AfxDebugBreak();
  491. #endif
  492. // resniffing
  493. m_pSniffedContainer->Flush();
  494. FireSniffing(m_httpQuery.GetMachine(),
  495. m_httpQuery.GetPNPDevice(),
  496. m_httpQuery.GetDeviceInstance(),
  497. m_httpQuery.GetGuidClass());
  498. if (m_strCurShooter.GetLength() > 0)
  499. {
  500. m_httpQuery.RemoveNodes(pApi);
  501. m_httpQuery.RestoreStatesFromServ();
  502. m_apgts.ClearBackup();
  503. m_apgts.DoContent(&m_httpQuery);
  504. m_apgts.RenderNext(strResult);
  505. m_apgts.Empty();
  506. }
  507. else
  508. m_dwExtendedErr = TSERR_NOT_STARTED;
  509. return strResult.AllocSysString();
  510. }
  511. BSTR CTSHOOTCtrl::PreLoadURL(LPCTSTR szRoot)
  512. {
  513. // SzRoot should look like one of these.
  514. // _T("http://www.microsoft.com/isapi/support/apgts/");
  515. // _T("http://localhost/isapi/support/apgts/");
  516. // _T("http://catbert.saltmine.com/scripts/apgts/");
  517. CString strResult;
  518. strResult = szRoot;
  519. strResult += PRELOAD_LIBRARY + m_strCurShooter +
  520. m_httpQuery.GetSubmitString(m_Conf.GetAPI()->api.pAPI);
  521. return strResult.AllocSysString();
  522. }
  523. const CString CTSHOOTCtrl::GetListPath()
  524. {
  525. if (!m_downloadURL.GetLength() || !m_downloadListFilename.GetLength())
  526. return _T("");
  527. return m_downloadURL + m_downloadListFilename;
  528. }
  529. //
  530. // Types:
  531. //
  532. // 0 = Get INI file contents and fill up list
  533. // Returns: 0 = ok, other = Error connecting
  534. //
  535. // 1 = Download and register DSC files based on list
  536. // Returns: 0 = ok, other = Error, typically no more data in list
  537. //
  538. // Notes:
  539. // 1. This function starts downloading and calls BindStatus event
  540. // as download progresses.
  541. // 2. Type 0 must always be called after type 1 is finished to reset
  542. // the list otherwise an error is returned
  543. // 3. Keep dwActionType and DLITEMTYPES in sync
  544. //
  545. long CTSHOOTCtrl::DownloadAction(long dwActionType)
  546. {
  547. DLITEMTYPES dwType;
  548. CString sURL;
  549. if (!GetListPath().GetLength())
  550. return LTSCERR_NOPATH;
  551. if (dwActionType == 0)
  552. {
  553. dwType = DLITEM_INI;
  554. sURL = GetListPath();
  555. // initialize to 'no error'
  556. m_dwExtendedErr = LTSC_OK;
  557. //m_bComplete = FALSE;
  558. }
  559. else if (dwActionType == 1)
  560. {
  561. //if (!m_bComplete)
  562. // return LTSCERR_DNLDNOTDONE;
  563. dwType = DLITEM_DSC;
  564. sURL = m_downloadURL;
  565. if (!m_dnldList.FindNextItem())
  566. return LTSC_NOMOREITEMS;
  567. sURL += m_dnldList.GetCurrFile();
  568. }
  569. else
  570. return LTSCERR_UNKNATYPE;
  571. if (m_download == NULL)
  572. m_download = new CDownload();
  573. if (m_download == NULL)
  574. return LTSCERR_NOMEM;
  575. HRESULT hr = m_download->DoDownload( this, sURL, dwType);
  576. if (FAILED(hr))
  577. return LTSCERR_DNLD;
  578. return LTSC_OK;
  579. }
  580. void CTSHOOTCtrl::OnDownloadListFilenameChanged()
  581. {
  582. SetModifiedFlag();
  583. }
  584. void CTSHOOTCtrl::OnDownloadURLChanged()
  585. {
  586. SetModifiedFlag();
  587. }
  588. BSTR CTSHOOTCtrl::GetCurrentFileDownload()
  589. {
  590. CString strResult = m_dnldList.GetCurrFile();
  591. return strResult.AllocSysString();
  592. }
  593. BSTR CTSHOOTCtrl::GetCurrentFriendlyDownload()
  594. {
  595. CString strResult = m_dnldList.GetCurrFriendly();
  596. return strResult.AllocSysString();
  597. }
  598. long CTSHOOTCtrl::GetExtendedError()
  599. {
  600. return (m_dwExtendedErr & 0x0000FFFF);
  601. }
  602. VOID CTSHOOTCtrl::StatusEventHelper(DLITEMTYPES dwItem,
  603. DLSTATTYPES dwStat,
  604. DWORD dwExtended,
  605. BOOL bComplete)
  606. {
  607. m_bComplete = bComplete;
  608. FireBindStatus(dwItem, dwStat, dwExtended, bComplete);
  609. }
  610. VOID CTSHOOTCtrl::ProgressEventHelper( DLITEMTYPES dwItem, ULONG ulCurr, ULONG ulTotal )
  611. {
  612. if (dwItem == DLITEM_INI)
  613. FireBindProgress(m_downloadListFilename, ulCurr, ulTotal);
  614. else
  615. FireBindProgress(m_dnldList.GetCurrFile(), ulCurr, ulTotal);
  616. }
  617. // Input data is null terminated for both binary and text data to simplify processing
  618. //
  619. DLSTATTYPES CTSHOOTCtrl::ProcessReceivedData(DLITEMTYPES dwItem, TCHAR *pData, UINT uLen)
  620. {
  621. DLSTATTYPES dwStat = LTSC_OK;
  622. switch(dwItem)
  623. {
  624. case DLITEM_INI:
  625. // processing INI file
  626. dwStat = ProcessINI(pData);
  627. break;
  628. case DLITEM_DSC:
  629. // processing DSC file
  630. dwStat = ProcessDSC(pData, uLen);
  631. break;
  632. default:
  633. dwStat = LTSCERR_UNSUPP;
  634. break;
  635. }
  636. return dwStat;
  637. }
  638. // Returns true if we need to update this file
  639. //
  640. BOOL CTSHOOTCtrl::FileRegCheck(CString &sType,
  641. CString &sFilename,
  642. CString &sKeyName,
  643. DWORD dwCurrVersion)
  644. {
  645. HKEY hk, hknew;
  646. BOOL bStat = FALSE;
  647. CString sMainKey;
  648. // figure out what our main key is for this file
  649. if (sType == TSINI_TYPE_TS)
  650. sMainKey = TSREGKEY_TL;
  651. else if (sType == TSINI_TYPE_SF)
  652. sMainKey = TSREGKEY_SFL;
  653. else
  654. {
  655. m_dwExtendedErr = LTSCERR_BADTYPE;
  656. return FALSE;
  657. }
  658. // first open the main key (try open all access now just in case of permissions problems)
  659. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  660. sMainKey,
  661. 0,
  662. KEY_ALL_ACCESS,
  663. &hk) == ERROR_SUCCESS)
  664. {
  665. CString sValueName;
  666. CString sValueClass;
  667. FILETIME ftLastWriteTime;
  668. DWORD count = 0;
  669. LONG ldStat = ERROR_SUCCESS;
  670. BOOL bFound = FALSE;
  671. while (ldStat == ERROR_SUCCESS)
  672. {
  673. LPTSTR lptname = sValueName.GetBuffer(MAX_PATH + 1);
  674. LPTSTR lptclass = sValueClass.GetBuffer(MAX_PATH + 1);
  675. DWORD namesize = MAX_PATH;
  676. DWORD classsize = MAX_PATH;
  677. ldStat = RegEnumKeyEx( hk,
  678. count,
  679. lptname,
  680. &namesize,
  681. NULL,
  682. lptclass,
  683. &classsize,
  684. &ftLastWriteTime);
  685. sValueName.ReleaseBuffer();
  686. sValueClass.ReleaseBuffer();
  687. if (ldStat != ERROR_SUCCESS)
  688. {
  689. break;
  690. }
  691. if (!sValueName.CompareNoCase(sKeyName))
  692. {
  693. // open specific troubleshooter key data (read only)
  694. if (RegOpenKeyEx( hk,
  695. sKeyName,
  696. 0,
  697. KEY_ALL_ACCESS,
  698. &hknew) == ERROR_SUCCESS)
  699. {
  700. DWORD dwData, dwValue;
  701. BYTE szValue[MAXCHAR];
  702. //dwData = REG_DWORD;
  703. dwData = REG_SZ;
  704. DWORD dwSize = MAXCHAR;
  705. if (RegQueryValueEx(hknew,
  706. TSLCL_FVERSION,
  707. 0,
  708. &dwData,
  709. szValue,
  710. &dwSize) == ERROR_SUCCESS)
  711. {
  712. dwValue = _ttoi((TCHAR *) szValue);
  713. if (dwValue < dwCurrVersion)
  714. bStat = TRUE;
  715. else
  716. {
  717. // check if file exists
  718. HANDLE hCurrFind;
  719. WIN32_FIND_DATA FindCurrData;
  720. CString sFullPath;
  721. sFullPath = m_sBasePath + _T("\\") + sFilename;
  722. hCurrFind = FindFirstFile(sFullPath, &FindCurrData);
  723. if (hCurrFind != INVALID_HANDLE_VALUE)
  724. {
  725. FindClose(hCurrFind);
  726. }
  727. else
  728. bStat = TRUE;
  729. }
  730. }
  731. else
  732. m_dwExtendedErr = LTSCERR_KEYQUERY;
  733. RegCloseKey(hknew);
  734. }
  735. else
  736. m_dwExtendedErr = LTSCERR_KEYOPEN2;
  737. // this is important: set this true to prevent default from trying to download
  738. // we wont download if we found the key but can't update
  739. bFound = TRUE;
  740. break;
  741. }
  742. count++;
  743. }
  744. if (!bFound)
  745. {
  746. bStat = TRUE;
  747. }
  748. RegCloseKey(hk);
  749. }
  750. else
  751. m_dwExtendedErr = LTSCERR_KEYOPEN;
  752. return bStat;
  753. }
  754. DLSTATTYPES CTSHOOTCtrl::ProcessINI(TCHAR *pData)
  755. {
  756. BOOL bFoundHeader = FALSE;
  757. int dwCount = 0;
  758. int dwMaxLines = 10000;
  759. DLSTATTYPES dwStat = LTSC_OK;
  760. dwStat = GetPathToFiles();
  761. if (dwStat != LTSC_OK)
  762. return dwStat;
  763. m_dnldList.RemoveAll();
  764. CString sData = pData;
  765. int dwFullLen = sData.GetLength();
  766. // just to be safe...
  767. while (dwMaxLines--)
  768. {
  769. CString sFullString = sData.SpanExcluding(_T("\r\n"));
  770. int dwPartLen = sFullString.GetLength();
  771. if (!dwPartLen)
  772. break;
  773. dwFullLen -= dwPartLen;
  774. CString sSkipString1 = sData.Right(dwFullLen);
  775. CString sSkipString2 = sSkipString1.SpanIncluding(_T("\r\n"));
  776. dwFullLen -= sSkipString2.GetLength();
  777. sData = sSkipString1.Right(dwFullLen);
  778. sFullString.TrimLeft();
  779. sFullString.TrimRight();
  780. int dwLineLen = sFullString.GetLength();
  781. if (!dwLineLen)
  782. continue;
  783. if (sFullString[0] == _T(';'))
  784. continue;
  785. if (sFullString == TSINI_GROUP_STR)
  786. {
  787. bFoundHeader = TRUE;
  788. continue;
  789. }
  790. else if (sFullString[0] == _T('['))
  791. {
  792. bFoundHeader = FALSE;
  793. continue;
  794. }
  795. if (bFoundHeader)
  796. {
  797. CString sParam[TSINI_LINE_PARAM_COUNT];
  798. int posstart = 0;
  799. // now break apart components
  800. for (int i=0;i<TSINI_LINE_PARAM_COUNT;i++)
  801. {
  802. int posend = sFullString.Find(_T(','));
  803. if (posend == -1 && i < (TSINI_LINE_PARAM_COUNT - 1))
  804. {
  805. m_dwExtendedErr = LTSCERR_PARAMMISS;
  806. break;
  807. }
  808. // so we don't find it next time
  809. if (posend != -1)
  810. sFullString.SetAt(posend, _T('.'));
  811. else
  812. posend = dwLineLen;
  813. sParam[i] = sFullString.Mid(posstart, posend - posstart);
  814. sParam[i].TrimLeft();
  815. sParam[i].TrimRight();
  816. posstart = posend + 1;
  817. }
  818. if (i==TSINI_LINE_PARAM_COUNT)
  819. {
  820. // add to object list if (1) version newer or (2) not in list yet
  821. CString sKeyName;
  822. DWORD dwVersion = _ttoi(sParam[TSINI_OFFSET_VERSION]);
  823. int pos;
  824. pos = sParam[TSINI_OFFSET_FILENAME].Find(_T('\\'));
  825. if (pos == -1)
  826. {
  827. pos = sParam[TSINI_OFFSET_FILENAME].Find(_T('.'));
  828. if (pos != -1)
  829. {
  830. if (sParam[TSINI_OFFSET_TYPE] == TSINI_TYPE_TS)
  831. sKeyName = sParam[TSINI_OFFSET_FILENAME].Left(pos);
  832. else {
  833. sKeyName = sParam[TSINI_OFFSET_FILENAME];
  834. //sKeyName.SetAt(pos, _T('_'));
  835. }
  836. // for now, check if we meet criteria
  837. // if yes, just add to list and download on a later iteration
  838. if (FileRegCheck(sParam[TSINI_OFFSET_TYPE], sParam[TSINI_OFFSET_FILENAME], sKeyName, dwVersion))
  839. {
  840. CDnldObj *pDnld = new CDnldObj( sParam[TSINI_OFFSET_TYPE],
  841. sParam[TSINI_OFFSET_FILENAME],
  842. dwVersion,
  843. sParam[TSINI_OFFSET_FRIENDLY],
  844. sKeyName);
  845. if (pDnld)
  846. {
  847. m_dnldList.AddTail(pDnld);
  848. dwCount++;
  849. }
  850. else
  851. {
  852. dwStat = LTSCERR_NOMEM;
  853. break;
  854. }
  855. }
  856. }
  857. else
  858. m_dwExtendedErr = LTSCERR_PARAMNODOT;
  859. }
  860. else
  861. m_dwExtendedErr = LTSCERR_PARAMSLASH;
  862. }
  863. }
  864. }
  865. ASSERT(dwCount == m_dnldList.GetCount());
  866. if (!dwCount)
  867. dwStat = LTSCERR_NOITEMS;
  868. m_dnldList.SetFirstItem();
  869. return dwStat;
  870. }
  871. //
  872. //
  873. DLSTATTYPES CTSHOOTCtrl::GetPathToFiles()
  874. {
  875. DLSTATTYPES dwStat = LTSC_OK;
  876. HKEY hk;
  877. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  878. TSREGKEY_MAIN,
  879. 0,
  880. KEY_READ,
  881. &hk) == ERROR_SUCCESS)
  882. {
  883. DWORD dwData = REG_SZ;
  884. DWORD dwSize = MAX_PATH;
  885. LPTSTR lptBuf = m_sBasePath.GetBuffer(MAX_PATH + 2);
  886. if (RegQueryValueEx(hk,
  887. FULLRESOURCE_STR,
  888. 0,
  889. &dwData,
  890. (LPBYTE) lptBuf,
  891. &dwSize) != ERROR_SUCCESS)
  892. {
  893. dwStat = LTSCERR_BASEKQ;
  894. }
  895. m_sBasePath.ReleaseBuffer();
  896. RegCloseKey(hk);
  897. }
  898. else
  899. dwStat = LTSCERR_NOBASEPATH;
  900. return dwStat;
  901. }
  902. DLSTATTYPES CTSHOOTCtrl::ProcessDSC(TCHAR *pData, UINT uLen)
  903. {
  904. DLSTATTYPES dwStat = LTSC_OK;
  905. HKEY hknew;
  906. DWORD dwDisposition;
  907. CString sMainKey;
  908. // we get here if we need to update this file
  909. // at this point we have the file downloaded and need to save it
  910. // we also need to create/update the necessary registry keys
  911. // since we know the entire key name, let's go ahead to create it
  912. if (m_dnldList.GetCurrType() == TSINI_TYPE_SF)
  913. sMainKey = TSREGKEY_SFL;
  914. else
  915. sMainKey = TSREGKEY_TL;
  916. sMainKey += _T("\\") + m_dnldList.GetCurrFileKey();
  917. // open specific troubleshooter key data
  918. if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  919. sMainKey,
  920. 0,
  921. TSLCL_REG_CLASS,
  922. REG_OPTION_NON_VOLATILE,
  923. KEY_ALL_ACCESS,
  924. NULL,
  925. &hknew,
  926. &dwDisposition) == ERROR_SUCCESS)
  927. {
  928. if (dwDisposition == REG_CREATED_NEW_KEY || dwDisposition == REG_OPENED_EXISTING_KEY)
  929. {
  930. DWORD dwData = m_dnldList.GetCurrVersion();
  931. CString str;
  932. str.Format(_T("%d"), dwData);
  933. if (RegSetValueEx( hknew,
  934. TSLCL_FVERSION,
  935. 0,
  936. //REG_DWORD,
  937. REG_SZ,
  938. (LPBYTE) (LPCTSTR) str,
  939. str.GetLength() + sizeof(TCHAR)) != ERROR_SUCCESS)
  940. {
  941. dwStat = LTSCERR_FILEUPDATE;
  942. m_dwExtendedErr = LTSCERR_KEYSET1;
  943. }
  944. if (dwStat == LTSC_OK)
  945. {
  946. CString sTemp = m_dnldList.GetCurrFriendly();
  947. DWORD dwSize = sTemp.GetLength() + sizeof(TCHAR);
  948. LPCTSTR lpctFN = sTemp.GetBuffer(100);
  949. if (RegSetValueEx( hknew,
  950. FRIENDLY_NAME,
  951. 0,
  952. REG_SZ,
  953. (LPBYTE) lpctFN,
  954. dwSize) == ERROR_SUCCESS)
  955. {
  956. CFile sF;
  957. CFileException exc;
  958. CString sFullPath;
  959. sFullPath = m_sBasePath + _T("\\") + m_dnldList.GetCurrFile();
  960. if (sF.Open(sFullPath, CFile::modeCreate | CFile::modeWrite, &exc))
  961. {
  962. TRY
  963. {
  964. sF.Write(pData, uLen);
  965. }
  966. CATCH (CFileException, e)
  967. {
  968. dwStat = LTSCERR_FILEUPDATE;
  969. m_dwExtendedErr = LTSCERR_FILEWRITE;
  970. }
  971. END_CATCH
  972. sF.Close();
  973. // uncompress if a cab file (be dumb, assume .cab really means a cab file)
  974. int pos = sFullPath.Find(_T('.'));
  975. if (pos != -1)
  976. {
  977. CString sTemp = sFullPath.Right(sFullPath.GetLength() - pos);
  978. if (!sTemp.CompareNoCase(_T(".cab")))
  979. {
  980. CCabUnCompress cab;
  981. CString strDestDir = m_sBasePath + "\\";
  982. if (!cab.ExtractCab(sFullPath, strDestDir, ""))
  983. {
  984. dwStat = LTSCERR_FILEUPDATE;
  985. m_dwExtendedErr = LTSCERR_CABWRITE;
  986. }
  987. TRY
  988. {
  989. CFile::Remove(sFullPath);
  990. }
  991. CATCH (CFileException, e)
  992. {
  993. // error is not very interesting
  994. }
  995. END_CATCH
  996. }
  997. }
  998. }
  999. else
  1000. {
  1001. dwStat = LTSCERR_FILEUPDATE;
  1002. m_dwExtendedErr = LTSCERR_FILEWRITE;
  1003. }
  1004. }
  1005. else
  1006. {
  1007. dwStat = LTSCERR_FILEUPDATE;
  1008. m_dwExtendedErr = LTSCERR_KEYSET2;
  1009. }
  1010. sTemp.ReleaseBuffer();
  1011. }
  1012. if (dwStat == LTSC_OK)
  1013. {
  1014. CString sTemp = m_dnldList.GetCurrExt();
  1015. DWORD dwSize = sTemp.GetLength() + sizeof(TCHAR);
  1016. LPCTSTR lpctFN = sTemp.GetBuffer(100);
  1017. if (RegSetValueEx( hknew,
  1018. TSLCL_FMAINEXT,
  1019. 0,
  1020. REG_SZ,
  1021. (LPBYTE) lpctFN,
  1022. dwSize) != ERROR_SUCCESS)
  1023. {
  1024. dwStat = LTSCERR_FILEUPDATE;
  1025. m_dwExtendedErr = LTSCERR_KEYSET3;
  1026. }
  1027. sTemp.ReleaseBuffer();
  1028. }
  1029. }
  1030. else
  1031. {
  1032. dwStat = LTSCERR_FILEUPDATE;
  1033. m_dwExtendedErr = LTSCERR_KEYUNSUPP;
  1034. }
  1035. RegCloseKey(hknew);
  1036. }
  1037. else
  1038. {
  1039. dwStat = LTSCERR_FILEUPDATE;
  1040. m_dwExtendedErr = LTSCERR_KEYCREATE;
  1041. }
  1042. return dwStat;
  1043. }
  1044. // Added 1/20/99 JM because RunQuery() can't be made to work with JScript, even though it
  1045. // worked fine with VB Script.
  1046. // Simulates the form in which RunQuery() would normally get its arguments, then pass them
  1047. // into RunQuery.
  1048. BSTR CTSHOOTCtrl::RunQuery2(LPCTSTR szTopic, LPCTSTR szCmd, LPCTSTR szVal)
  1049. {
  1050. VARIANT varCommands;
  1051. VARIANT varValues;
  1052. VARIANT varCommandsWrap;
  1053. VARIANT varValuesWrap;
  1054. SAFEARRAY *psafearrayCmds;
  1055. SAFEARRAY *psafearrayVals;
  1056. VariantInit(&varCommands);
  1057. VariantInit(&varValues);
  1058. VariantInit(&varCommandsWrap);
  1059. VariantInit(&varValuesWrap);
  1060. SAFEARRAYBOUND sabCmd;
  1061. sabCmd.cElements = 2;
  1062. sabCmd.lLbound = 0;
  1063. SAFEARRAYBOUND sabVal = sabCmd;
  1064. V_VT(&varCommands) = VT_ARRAY | VT_BYREF | VT_VARIANT;
  1065. V_VT(&varValues) = VT_ARRAY | VT_BYREF | VT_VARIANT;
  1066. V_ARRAYREF(&varCommands) = &psafearrayCmds;
  1067. V_ARRAYREF(&varValues) = &psafearrayVals;
  1068. V_VT(&varCommandsWrap) = VT_BYREF | VT_VARIANT;
  1069. V_VT(&varValuesWrap) = VT_BYREF | VT_VARIANT;
  1070. V_VARIANTREF(&varCommandsWrap) = &varCommands;
  1071. V_VARIANTREF(&varValuesWrap) = &varValues;
  1072. // If first character in szCmd is a null, then there will be only one significant
  1073. // element in each of the arrays we are constructing below, otherwise 2.
  1074. short size = (*szCmd) ? 2 : 1;
  1075. CString strType(C_TYPE);
  1076. BSTR bstrType = strType.AllocSysString();
  1077. VARIANT varType;
  1078. VariantInit(&varType);
  1079. V_VT(&varType) = VT_BSTR;
  1080. varType.bstrVal=bstrType;
  1081. CString strTopic(szTopic);
  1082. BSTR bstrTopic = strTopic.AllocSysString();
  1083. VARIANT varTopic;
  1084. VariantInit(&varTopic);
  1085. V_VT(&varTopic) = VT_BSTR;
  1086. varTopic.bstrVal=bstrTopic;
  1087. CString strCmd(szCmd);
  1088. BSTR bstrCmd = strCmd.AllocSysString();
  1089. VARIANT varCmd;
  1090. VariantInit(&varCmd);
  1091. V_VT(&varCmd) = VT_BSTR;
  1092. varCmd.bstrVal=bstrCmd;
  1093. CString strVal(szVal);
  1094. BSTR bstrVal = strVal.AllocSysString();
  1095. VARIANT varVal;
  1096. VariantInit(&varVal);
  1097. V_VT(&varVal) = VT_BSTR;
  1098. varVal.bstrVal=bstrVal;
  1099. // create two vectors of BSTRs
  1100. psafearrayCmds = SafeArrayCreate( VT_VARIANT, 1, &sabCmd);
  1101. psafearrayVals = SafeArrayCreate( VT_VARIANT, 1, &sabVal);
  1102. long i=0;
  1103. SafeArrayPutElement(psafearrayCmds, &i, &varType);
  1104. SafeArrayPutElement(psafearrayVals, &i, &varTopic);
  1105. i=1;
  1106. SafeArrayPutElement(psafearrayCmds, &i, &varCmd);
  1107. SafeArrayPutElement(psafearrayVals, &i, &varVal);
  1108. BSTR ret = RunQuery(varCommandsWrap, varValuesWrap, size);
  1109. SafeArrayDestroy(psafearrayCmds);
  1110. SafeArrayDestroy(psafearrayVals);
  1111. SysFreeString(bstrType);
  1112. SysFreeString(bstrTopic);
  1113. SysFreeString(bstrCmd);
  1114. SysFreeString(bstrVal);
  1115. return ret;
  1116. }
  1117. // This function is a no-op and exist solely to allow us to write JScript that is
  1118. // forward compatible to Local Troubleshooter version 3.1
  1119. void CTSHOOTCtrl::SetPair(LPCTSTR szName, LPCTSTR szValue)
  1120. {
  1121. }