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.

578 lines
15 KiB

  1. //
  2. // MODULE: StateInfo.cpp
  3. //
  4. // PURPOSE: Contains sniffing, network and node information. Also is used
  5. // by the Launch module to start the container application.
  6. //
  7. // Basically, this is how the Launch Server packages up info for the
  8. // Local TShoot OCX, launches either IE or HTML Help System to a page
  9. // containing the Local TShoot OCX, and handshakes with the Local TShoot OCX
  10. // to pass that information
  11. //
  12. // Note that CSMStateInfo::GetShooterStates() is called by the
  13. // Local TShoot OCX to pick up the CItem object which contains
  14. // the packaged-up info.
  15. //
  16. // PROJECT: Local Troubleshooter Launcher for the Device Manager
  17. //
  18. // COMPANY: Saltmine Creative, Inc. (206)-633-4743 [email protected]
  19. //
  20. // AUTHOR: Richard Meadows
  21. // COMMENTS BY: Joe Mabel
  22. //
  23. // ORIGINAL DATE: 2-26-98
  24. //
  25. //
  26. // Version Date By Comments
  27. //--------------------------------------------------------------------
  28. // V0.1 - RM Original
  29. ///////////////////////
  30. #include "stdafx.h"
  31. #include "atlbase.h"
  32. #include "StateInfo.h"
  33. #include "TSLError.h"
  34. #include "ComGlobals.h"
  35. #include "Registry.h"
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <memory.h>
  39. //#include <fstream.h>
  40. #include <strstrea.h>
  41. ////////////////////////////////////////////////////////
  42. // CItem :
  43. // Data structure for pseudo HTTP "get" in launching Local Troubleshooters
  44. //
  45. CItem::CItem()
  46. {
  47. // initializing this is exactly the same as reinitializing.
  48. ReInit();
  49. }
  50. void CItem::ReInit()
  51. {
  52. memset(m_aszCmds, NULL, SYM_LEN * NODE_COUNT);
  53. memset(m_aszVals, NULL, SYM_LEN * NODE_COUNT);
  54. m_cNodesSet = 0;
  55. _tcscpy(m_szProblemDef, _T("TShootProblem"));
  56. _tcscpy(m_szTypeDef, _T("type"));
  57. m_szPNPDeviceID[0] = NULL;
  58. m_szGuidClass[0] = NULL;
  59. m_szContainerPathName[0] = NULL;
  60. m_szWebPage[0] = NULL;
  61. m_szSniffScriptFile[0] = NULL;
  62. m_eLaunchRegime = launchIndefinite;
  63. m_szMachineID[0] = NULL;
  64. m_szDeviceInstanceID[0] = NULL;
  65. #ifdef _DEBUG
  66. // There are some other things you need to comment out in GetShooterStates
  67. // to allow debugging this service from a tshoot.ocx debug sesstion.
  68. /*
  69. _tcscpy(m_aszCmds[0], m_szTypeDef);
  70. _tcscpy(m_aszVals[0], _T("ras"));
  71. _tcscpy(m_aszCmds[1], m_szProblemDef);
  72. _tcscpy(m_aszVals[1], _T("CnntCnnctAftrDlngWthRS"));
  73. _tcscpy(m_aszCmds[2], _T("SoftwareCompression"));
  74. _tcscpy(m_aszVals[2], _T("0"));
  75. m_cNodesSet = 1;
  76. */
  77. #endif
  78. return;
  79. }
  80. void CItem::Clear()
  81. {
  82. memset(m_aszCmds, NULL, SYM_LEN * NODE_COUNT);
  83. memset(m_aszVals, NULL, SYM_LEN * NODE_COUNT);
  84. m_cNodesSet = 0;
  85. _tcscpy(m_szProblemDef, _T("TShootProblem"));
  86. _tcscpy(m_szTypeDef, _T("type"));
  87. m_szPNPDeviceID[0] = NULL;
  88. m_szGuidClass[0] = NULL;
  89. m_szContainerPathName[0] = NULL;
  90. m_szWebPage[0] = NULL;
  91. m_szSniffScriptFile[0] = NULL;
  92. m_eLaunchRegime = launchIndefinite;
  93. return;
  94. }
  95. // ----------- Routines to build command/value pairs ------------------
  96. // see documentation of m_aszCmds, m_aszVals for further explanation
  97. void CItem::SetNetwork(LPCTSTR szNetwork)
  98. {
  99. if (NULL != szNetwork && NULL != szNetwork[0])
  100. {
  101. _tcscpy(m_aszCmds[0], m_szTypeDef);
  102. _tcsncpy(m_aszVals[0], szNetwork, SYM_LEN);
  103. }
  104. else
  105. {
  106. m_aszCmds[0][0] = NULL;
  107. m_aszVals[0][0] = NULL;
  108. }
  109. return;
  110. }
  111. void CItem::SetProblem(LPCTSTR szProblem)
  112. {
  113. if (NULL != szProblem && NULL != szProblem[0])
  114. {
  115. _tcscpy(m_aszCmds[1], m_szProblemDef);
  116. _tcsncpy(m_aszVals[1], szProblem, SYM_LEN);
  117. }
  118. else
  119. {
  120. m_aszCmds[1][0] = NULL;
  121. m_aszVals[1][0] = NULL;
  122. }
  123. return;
  124. }
  125. void CItem::SetNode(LPCTSTR szNode, LPCTSTR szState)
  126. {
  127. if (NULL != szNode && NULL != szNode[0]
  128. && NULL != szState && NULL != szState[0])
  129. {
  130. _tcsncpy(m_aszCmds[m_cNodesSet + 2], szNode, SYM_LEN);
  131. _tcsncpy(m_aszVals[m_cNodesSet + 2], szState, SYM_LEN);
  132. m_cNodesSet++;
  133. }
  134. return;
  135. }
  136. // ----------- Routines to query command/value pairs ------------------
  137. // See documentation of m_aszCmds, m_aszVals for further explanation
  138. // returns true if network has been set
  139. // On success, OUTPUT *pszCmd is "type", *pszVal is network name
  140. bool CItem::GetNetwork(LPTSTR *pszCmd, LPTSTR *pszVal)
  141. {
  142. *pszCmd = m_szTypeDef;
  143. *pszVal = m_aszVals[0];
  144. return *m_aszVals[0] != NULL;
  145. }
  146. // returns true if problem node has been set
  147. // On success, OUTPUT *pszCmd is "TShootProblem", *pszVal is problem node's symbolic name
  148. bool CItem::GetProblem(LPTSTR *pszCmd, LPTSTR *pszVal)
  149. {
  150. *pszCmd = m_szProblemDef;
  151. *pszVal = m_aszVals[1];
  152. return *m_aszVals[1] != NULL;;
  153. }
  154. // output the iNodeC-th non-problem node for which a state has been set.
  155. // On success, OUTPUT *pszCmd is symbolic node name, *pszVal is state
  156. // returns true if at least iNodeC non-problem nodes have been set
  157. bool CItem::GetNodeState(int iNodeC, LPTSTR *pszCmd, LPTSTR *pszVal)
  158. {
  159. if (iNodeC >= m_cNodesSet)
  160. return false;
  161. *pszCmd = m_aszCmds[iNodeC + 2];
  162. *pszVal = m_aszVals[iNodeC + 2];
  163. return true;
  164. }
  165. // ----------- Routines to query whether we know a network ------------
  166. // ----------- & problem node to launch to ----------------------------
  167. // See documentation of m_aszCmds, m_aszVals for further explanation
  168. // NetworkSet returns true if we know which troubleshooter to launch.
  169. bool CItem::NetworkSet()
  170. {
  171. return NULL != m_aszVals[0][0];
  172. }
  173. // ProblemSet returns true if we know which problem to choose.
  174. bool CItem::ProblemSet()
  175. {
  176. return NULL != m_aszVals[1][0];
  177. }
  178. // --------- Interface to other member variables recponsible for launching -----------
  179. void CItem::SetLaunchRegime(ELaunchRegime eLaunchRegime)
  180. {
  181. m_eLaunchRegime = eLaunchRegime;
  182. }
  183. void CItem::SetContainerPathName(TCHAR szContainerPathName[MAX_PATH])
  184. {
  185. if (NULL != szContainerPathName && NULL != szContainerPathName[0])
  186. _tcscpy(m_szContainerPathName, szContainerPathName);
  187. else
  188. m_szContainerPathName[0] = NULL;
  189. return;
  190. }
  191. void CItem::SetWebPage(TCHAR szWebPage[MAX_PATH])
  192. {
  193. if (NULL != szWebPage && NULL != szWebPage[0])
  194. _tcscpy(m_szWebPage, szWebPage);
  195. else
  196. m_szWebPage[0] = NULL;
  197. return;
  198. }
  199. void CItem::SetSniffScriptFile(TCHAR szSniffScriptFile[MAX_PATH])
  200. {
  201. if (NULL != szSniffScriptFile && NULL != szSniffScriptFile[0])
  202. _tcscpy(m_szSniffScriptFile, szSniffScriptFile);
  203. else
  204. m_szSniffScriptFile[0] = NULL;
  205. return;
  206. }
  207. void CItem::SetSniffStandardFile(TCHAR szSniffStandardFile[MAX_PATH])
  208. {
  209. if (NULL != szSniffStandardFile && NULL != szSniffStandardFile[0])
  210. _tcscpy(m_szSniffStandardFile, szSniffStandardFile);
  211. else
  212. m_szSniffStandardFile[0] = NULL;
  213. return;
  214. }
  215. ELaunchRegime CItem::GetLaunchRegime()
  216. {
  217. return m_eLaunchRegime;
  218. }
  219. inline TCHAR* CItem::GetContainerPathName()
  220. {
  221. return m_szContainerPathName;
  222. }
  223. inline TCHAR* CItem::GetWebPage()
  224. {
  225. return m_szWebPage;
  226. }
  227. inline TCHAR* CItem::GetSniffScriptFile()
  228. {
  229. return m_szSniffScriptFile;
  230. }
  231. inline TCHAR* CItem::GetSniffStandardFile()
  232. {
  233. return m_szSniffStandardFile;
  234. }
  235. ////////////////////////////////////////////////////////
  236. // CSMStateInfo :
  237. // State information on MSBN Troubleshooters
  238. //
  239. CSMStateInfo::CSMStateInfo()
  240. {
  241. m_csGlobalMemory.Init();
  242. m_csSingleLaunch.Init();
  243. return;
  244. }
  245. CSMStateInfo::~CSMStateInfo()
  246. {
  247. m_csGlobalMemory.Term();
  248. m_csSingleLaunch.Term();
  249. return;
  250. }
  251. // TestPut: Simply copies item to m_Item.
  252. void CSMStateInfo::TestPut(CItem &item)
  253. {
  254. m_csGlobalMemory.Lock();
  255. m_Item = item;
  256. m_csGlobalMemory.Unlock();
  257. return;
  258. }
  259. // TestGet: Simply copies m_Item to item.
  260. void CSMStateInfo::TestGet(CItem &item)
  261. {
  262. m_csGlobalMemory.Lock();
  263. item = m_Item;
  264. m_csGlobalMemory.Unlock();
  265. return;
  266. }
  267. // Copy the item to the global memory and launch a process based on the command.
  268. // Copying the item to global memory is here because the item is what tells the
  269. // launched local troubleshooter what belief network etc. it is being launched to.
  270. // Once we unlock global memory, the Local Troubleshooter OCX can read that item
  271. // and act on it.
  272. BOOL CSMStateInfo::CreateContainer(CItem &item, LPTSTR szCommand)
  273. {
  274. BOOL bOk = TRUE;
  275. HRESULT hRes = S_OK;
  276. STARTUPINFO startup;
  277. PROCESS_INFORMATION process;
  278. memset(&startup, NULL, sizeof(STARTUPINFO));
  279. startup.cb = sizeof(STARTUPINFO);
  280. startup.wShowWindow = SW_SHOWNORMAL;
  281. m_csGlobalMemory.Lock();
  282. m_Item = item;
  283. bOk = CreateProcess(NULL, szCommand, NULL, NULL, FALSE, 0, NULL, NULL,
  284. &startup, &process);
  285. CloseHandle(process.hThread);
  286. CloseHandle(process.hProcess);
  287. m_csGlobalMemory.Unlock();
  288. return bOk;
  289. }
  290. //
  291. // Copy network_sniff.htm to tssniffAsk.htm if the former exists
  292. // Create (modify) tssniffAsk.htm to be a sniffing stub otherwise
  293. //
  294. BOOL CSMStateInfo::CopySniffScriptFile(CItem &item)
  295. {
  296. TCHAR* szSniffScriptFile = item.GetSniffScriptFile();
  297. TCHAR* szSniffStandardFile = item.GetSniffStandardFile();
  298. if (!*szSniffScriptFile) // no network specific sniff file
  299. {
  300. // szSniffScriptFile contains tssniffAsk.htm
  301. // it means that we have to form this file as an empty stub
  302. ostrstream fileSniffScript;
  303. HANDLE hFile = ::CreateFile(szSniffStandardFile,
  304. GENERIC_WRITE,
  305. 0,
  306. NULL, // no security attributes
  307. CREATE_ALWAYS,
  308. FILE_FLAG_RANDOM_ACCESS,
  309. NULL // handle to template file
  310. );
  311. if (hFile != INVALID_HANDLE_VALUE)
  312. {
  313. // form html file - part preceding script
  314. fileSniffScript << "<HTML>" << endl;
  315. fileSniffScript << "<HEAD>" << endl;
  316. fileSniffScript << "<TITLE>GTS LOCAL</TITLE>" << endl;
  317. fileSniffScript << "</HEAD>" << endl;
  318. fileSniffScript << "<SCRIPT LANGUAGE=\"VBSCRIPT\">" << endl;
  319. fileSniffScript << "<!--" << endl;
  320. // form global function
  321. fileSniffScript << "function PerformSniffing()" << endl;
  322. fileSniffScript << "end function" << endl;
  323. // form html file - part after script
  324. fileSniffScript << "-->" << endl;
  325. fileSniffScript << "</SCRIPT>" << endl;
  326. fileSniffScript << "<BODY BGCOLOR=\"#FFFFFF\">" << endl;
  327. fileSniffScript << "</BODY>" << endl;
  328. fileSniffScript << "</HTML>" << endl;
  329. fileSniffScript << ends;
  330. char* str = fileSniffScript.str();
  331. DWORD read;
  332. if (!::WriteFile(hFile, str, strlen(str), &read, NULL))
  333. {
  334. ::CloseHandle(hFile);
  335. fileSniffScript.rdbuf()->freeze(0);
  336. return false;
  337. }
  338. ::CloseHandle(hFile);
  339. fileSniffScript.rdbuf()->freeze(0);
  340. return true;
  341. }
  342. else
  343. {
  344. return false;
  345. }
  346. }
  347. else
  348. {
  349. return ::CopyFile(szSniffScriptFile, szSniffStandardFile, false);
  350. }
  351. }
  352. // Find the container (HTML Help System or IE) and starting web page, launch, wait to
  353. // see if launch succeeded
  354. bool CSMStateInfo::GoGo(DWORD dwTimeOut, CItem &item, DWORD *pdwResult)
  355. {
  356. bool bResult = true;
  357. HANDLE hLaunchedEvent = NULL;
  358. TCHAR szProcess[MAX_PATH];
  359. TCHAR szWebPage[MAX_PATH];
  360. LPTSTR pszCommand = NULL;
  361. int CommandLen;
  362. DWORD dwError;
  363. int Count = 34;
  364. if (item.GetLaunchRegime() == launchIndefinite ||
  365. !item.GetContainerPathName()[0] ||
  366. !item.GetWebPage()[0]
  367. )
  368. {
  369. *pdwResult = TSL_ERROR_ASSERTION;
  370. return false;
  371. }
  372. do
  373. {
  374. _stprintf(item.m_szEventName, _T("TSL_SHOOTER_Event_%ld"), Count);
  375. if (NULL == (hLaunchedEvent = CreateEvent (NULL, FALSE, FALSE, item.m_szEventName)))
  376. {
  377. dwError = GetLastError();
  378. if (ERROR_ALREADY_EXISTS != dwError)
  379. {
  380. *pdwResult = dwError;
  381. return false;
  382. }
  383. }
  384. } while (NULL == hLaunchedEvent);
  385. // Get the path to internet explorer (or HTML Help System).
  386. _tcscpy(szProcess, item.GetContainerPathName());
  387. // Need to know the location and name of the
  388. // page that asks the service for the CItem
  389. // information.
  390. _tcscpy(szWebPage, item.GetWebPage());
  391. CommandLen = _tcslen(szProcess) + 1 + _tcslen(szWebPage) + 2;
  392. pszCommand = new TCHAR[CommandLen];
  393. if (NULL == pszCommand)
  394. {
  395. *pdwResult = TSL_ERROR_OUT_OF_MEMORY;
  396. return false;
  397. }
  398. _tcscpy(pszCommand, szProcess);
  399. _tcscat(pszCommand, _T(" "));
  400. _tcscat(pszCommand, szWebPage);
  401. m_csSingleLaunch.Lock();
  402. // copy to or create tssniffAsk.htm
  403. if (!CopySniffScriptFile(item))
  404. {
  405. *pdwResult = TSL_E_COPY_SNIFF_SCRIPT;
  406. return false;
  407. }
  408. // CreateContainer copies the item to the global memory and
  409. // launches the command.
  410. if (!CreateContainer(item, pszCommand))
  411. {
  412. *pdwResult = TSL_E_CREATE_PROC;
  413. bResult = false;
  414. }
  415. else
  416. {
  417. if (WAIT_OBJECT_0 == WaitForSingleObject(hLaunchedEvent, dwTimeOut))
  418. { // The container has the information.
  419. *pdwResult = TSL_OK;
  420. }
  421. else
  422. { // Wait timed out. Don't know if the operation will work or not work.
  423. *pdwResult = TSL_W_CONTAINER_WAIT_TIMED_OUT;
  424. }
  425. }
  426. m_csSingleLaunch.Unlock();
  427. delete [] pszCommand;
  428. CloseHandle(hLaunchedEvent);
  429. return bResult;
  430. }
  431. // Find the container (HTML Help System or IE) and start it up to a URL which is _not_
  432. // expected to contain Local Troubleshooter, just an arbitrary web page. This should
  433. // only be used when the launch as such can't work, and we are just trying to give them
  434. // somewhere to start troubleshooting, typically the home page which lists all
  435. // trobleshooting belief networks.
  436. bool CSMStateInfo::GoURL(CItem &item, DWORD *pdwResult)
  437. {
  438. bool bResult = true;
  439. TCHAR szProcess[MAX_PATH];
  440. TCHAR szWebPage[MAX_PATH];
  441. LPTSTR pszCommand = NULL;
  442. int CommandLen;
  443. if (item.GetLaunchRegime() != launchDefaultWebPage ||
  444. !item.GetContainerPathName()[0] ||
  445. !item.GetWebPage()[0]
  446. )
  447. {
  448. *pdwResult = TSL_ERROR_ASSERTION;
  449. return false;
  450. }
  451. // Get the path to internet explorer (or HTML Help System).
  452. _tcscpy(szProcess, item.GetContainerPathName());
  453. // Need to know the location and name of the
  454. // page that asks the service for the CItem
  455. // information.
  456. _tcscpy(szWebPage, item.GetWebPage());
  457. CommandLen = _tcslen(szProcess) + 1 + _tcslen(szWebPage) + 2;
  458. pszCommand = new TCHAR[CommandLen];
  459. if (NULL == pszCommand)
  460. {
  461. *pdwResult = TSL_ERROR_OUT_OF_MEMORY;
  462. return false;
  463. }
  464. _tcscpy(pszCommand, szProcess);
  465. _tcscat(pszCommand, _T(" "));
  466. _tcscat(pszCommand, szWebPage);
  467. // CreateContainer is overkill here, but perfectly OK.
  468. if (!CreateContainer(item, pszCommand))
  469. {
  470. *pdwResult = TSL_E_CREATE_PROC;
  471. bResult = false;
  472. }
  473. delete [] pszCommand;
  474. return bResult;
  475. }
  476. // This function is used by the Local Troubleshooter OCX, not by the Launcher.
  477. // This is how the Local Troubleshooter knows what troubleshooting network to launch
  478. // to, as well as any nodes whose states are set.
  479. // GetShooterStates returns the commands and the number of commands for
  480. // the Tshoot.ocx.
  481. // refLaunchState is a member of this instance of the LaunchTS interface.
  482. //
  483. HRESULT CSMStateInfo::GetShooterStates(CItem &refLaunchState, DWORD *pdwResult)
  484. {
  485. HANDLE hHaveItemEvent;
  486. // Get a copy of the launch info state stored in this instance.
  487. // Synchronize with the process that launched the service.
  488. m_csGlobalMemory.Lock();
  489. if (NULL == (hHaveItemEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, m_Item.m_szEventName)))
  490. {
  491. *pdwResult = GetLastError();
  492. m_csGlobalMemory.Unlock();
  493. return TSL_E_FAIL;
  494. }
  495. // Get a copy of the state before unlocking the global memory.
  496. refLaunchState = m_Item;
  497. // Let the other process continue running.
  498. SetEvent(hHaveItemEvent);
  499. m_csGlobalMemory.Unlock();
  500. CloseHandle(hHaveItemEvent);
  501. *pdwResult = 0;
  502. return S_OK;
  503. }