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.

668 lines
20 KiB

  1. // pwsDoc.cpp : implementation of the CPwsDoc class
  2. //
  3. #include "stdafx.h"
  4. #include "resource.h"
  5. #include "pwsform.h"
  6. #include "Title.h"
  7. #include "HotLink.h"
  8. #include "PWSChart.h"
  9. #include "pwsDoc.h"
  10. //#include "PwsForm.h"
  11. #include "Tip.h"
  12. #include "TipDlg.h"
  13. #include "EdDir.h"
  14. #include "FormMain.h"
  15. #include "FormAdv.h"
  16. #include <isvctrl.h>
  17. #include "ServCntr.h"
  18. #include "pwstray.h"
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24. // location of the installation path in the registry
  25. #define REG_INSTALL_PATH _T("Software\\Microsoft\\InetStp")
  26. #define REG_PATH_VAL _T("InstallPath")
  27. #define SZ_KEY_RUN_TRAY _T("software\\microsoft\\windows\\currentversion\\run")
  28. #define SZ_KEY_RUN_VALUE _T("PWSTray")
  29. #define SERVER_WINDOWCLASS_NAME TEXT(INET_SERVER_WINDOW_CLASS)
  30. // globals
  31. //extern CPwsForm* g_p_FormView;
  32. CPwsDoc* g_p_Doc = NULL;
  33. extern CFormMain* g_FormMain;
  34. extern IMSAdminBase* g_pMBCom;
  35. extern BOOL g_fShutdownMode;
  36. #define REGKEY_STP _T("SOFTWARE\\Microsoft\\INetStp")
  37. #define REGKEY_INSTALLKEY _T("InstallPath")
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CPwsDoc
  40. IMPLEMENT_DYNCREATE(CPwsDoc, CDocument)
  41. BEGIN_MESSAGE_MAP(CPwsDoc, CDocument)
  42. //{{AFX_MSG_MAP(CPwsDoc)
  43. ON_COMMAND(ID_START, OnStart)
  44. ON_COMMAND(ID_STOP, OnStop)
  45. ON_UPDATE_COMMAND_UI(ID_START, OnUpdateStart)
  46. ON_UPDATE_COMMAND_UI(ID_STOP, OnUpdateStop)
  47. ON_COMMAND(ID_PAUSE, OnPause)
  48. ON_UPDATE_COMMAND_UI(ID_PAUSE, OnUpdatePause)
  49. ON_COMMAND(ID_SHOW_TIPS, OnShowTips)
  50. ON_UPDATE_COMMAND_UI(ID_SHOW_TIPS, OnUpdateShowTips)
  51. ON_COMMAND(ID_HELP_DOCUMENTATION, OnHelpDocumentation)
  52. ON_COMMAND(ID_HELP_HELP_TROUBLESHOOTING, OnHelpHelpTroubleshooting)
  53. ON_UPDATE_COMMAND_UI(ID_CONTINUE, OnUpdateContinue)
  54. ON_COMMAND(ID_CONTINUE, OnContinue)
  55. ON_UPDATE_COMMAND_UI(ID_TRAYICON, OnUpdateTrayicon)
  56. ON_COMMAND(ID_TRAYICON, OnTrayicon)
  57. //}}AFX_MSG_MAP
  58. END_MESSAGE_MAP()
  59. BEGIN_DISPATCH_MAP(CPwsDoc, CDocument)
  60. //{{AFX_DISPATCH_MAP(CPwsDoc)
  61. // NOTE - the ClassWizard will add and remove mapping macros here.
  62. // DO NOT EDIT what you see in these blocks of generated code!
  63. //}}AFX_DISPATCH_MAP
  64. END_DISPATCH_MAP()
  65. static const IID IID_IPws =
  66. { 0x35c43e1, 0x8464, 0x11d0, { 0xa9, 0x2d, 0x8, 0x0, 0x2b, 0x2c, 0x6f, 0x32 } };
  67. BEGIN_INTERFACE_MAP(CPwsDoc, CDocument)
  68. INTERFACE_PART(CPwsDoc, IID_IPws, Dispatch)
  69. END_INTERFACE_MAP()
  70. /////////////////////////////////////////////////////////////////////////////
  71. // CPwsDoc construction/destruction
  72. //------------------------------------------------------------------
  73. CPwsDoc::CPwsDoc():
  74. m_ActionToDo( 0 ),
  75. m_ExpectedResult( 0 ),
  76. m_dwSinkCookie( 0 ),
  77. m_pEventSink( NULL ),
  78. m_pConnPoint( NULL ),
  79. m_fIsPWSTrayAvailable( FALSE )
  80. {
  81. EnableAutomation();
  82. AfxOleLockApp();
  83. g_p_Doc = this;
  84. OSVERSIONINFO info_os;
  85. info_os.dwOSVersionInfoSize = sizeof(info_os);
  86. // record what sort of operating system we are running on
  87. m_fIsWinNT = FALSE;
  88. if ( GetVersionEx( &info_os ) )
  89. {
  90. if ( info_os.dwPlatformId == VER_PLATFORM_WIN32_NT )
  91. m_fIsWinNT = TRUE;
  92. }
  93. }
  94. //------------------------------------------------------------------
  95. CPwsDoc::~CPwsDoc()
  96. {
  97. TerminateSink();
  98. g_p_Doc = NULL;
  99. AfxOleUnlockApp();
  100. }
  101. //------------------------------------------------------------------
  102. // builds something akin to "http://boydm"
  103. BOOL CPwsDoc::BuildHomePageString( CString &cs )
  104. {
  105. CHAR nameBuf[MAX_PATH+1];
  106. // if the server is not running, fail
  107. CW3ServerControl serverController;
  108. if ( serverController.GetServerState() != MD_SERVER_STATE_STARTED )
  109. return FALSE;
  110. // start it off with the mandatory http header
  111. cs.LoadString( IDS_HTTP_HEADER );
  112. // get the host name of the machine
  113. gethostname( nameBuf, sizeof(nameBuf));
  114. cs += nameBuf;
  115. return TRUE;
  116. }
  117. //------------------------------------------------------------------
  118. BOOL CPwsDoc::InitializeSink()
  119. {
  120. IConnectionPointContainer * pConnPointContainer = NULL;
  121. HRESULT hRes;
  122. BOOL fSinkConnected = FALSE;
  123. // g_pMBCom is defined in wrapmb
  124. IUnknown* pmb = (IUnknown*)g_pMBCom;
  125. m_pEventSink = new CImpIMSAdminBaseSink();
  126. if ( !m_pEventSink )
  127. {
  128. return FALSE;
  129. }
  130. //
  131. // First query the object for its Connection Point Container. This
  132. // essentially asks the object in the server if it is connectable.
  133. //
  134. hRes = pmb->QueryInterface( IID_IConnectionPointContainer,
  135. (PVOID *)&pConnPointContainer);
  136. if SUCCEEDED(hRes)
  137. {
  138. // Find the requested Connection Point. This AddRef's the
  139. // returned pointer.
  140. hRes = pConnPointContainer->FindConnectionPoint( IID_IMSAdminBaseSink,
  141. &m_pConnPoint);
  142. if (SUCCEEDED(hRes))
  143. {
  144. hRes = m_pConnPoint->Advise( (IUnknown *)m_pEventSink,
  145. &m_dwSinkCookie);
  146. if (SUCCEEDED(hRes))
  147. {
  148. fSinkConnected = TRUE;
  149. }
  150. }
  151. if ( pConnPointContainer )
  152. {
  153. pConnPointContainer->Release();
  154. pConnPointContainer = NULL;
  155. }
  156. }
  157. if ( !fSinkConnected )
  158. {
  159. delete m_pEventSink;
  160. }
  161. return fSinkConnected;
  162. }
  163. //------------------------------------------------------------------
  164. void CPwsDoc::TerminateSink()
  165. {
  166. HRESULT hRes;
  167. if ( m_dwSinkCookie )
  168. {
  169. hRes = m_pConnPoint->Unadvise( m_dwSinkCookie );
  170. }
  171. // don't need to delete m_pEventSink because the Unadvise
  172. // above decrements is reference count and that causes it
  173. // to delete itself....
  174. }
  175. //------------------------------------------------------------------
  176. BOOL CPwsDoc::OnNewDocument()
  177. {
  178. if (!CDocument::OnNewDocument())
  179. return FALSE;
  180. if (!FInitServerInfo())
  181. return FALSE;
  182. // start up the sink
  183. InitializeSink();
  184. // see if the pwstray executable is available
  185. CString pathTray;
  186. if ( GetPWSTrayPath(pathTray) )
  187. {
  188. m_fIsPWSTrayAvailable = (GetFileAttributes(pathTray) != 0xFFFFFFFF);
  189. }
  190. // return success
  191. return TRUE;
  192. }
  193. /////////////////////////////////////////////////////////////////////////////
  194. // CPwsDoc serialization
  195. //------------------------------------------------------------------
  196. void CPwsDoc::Serialize(CArchive& ar)
  197. {
  198. if (ar.IsStoring())
  199. {
  200. }
  201. else
  202. {
  203. }
  204. }
  205. /////////////////////////////////////////////////////////////////////////////
  206. // CPwsDoc diagnostics
  207. #ifdef _DEBUG
  208. //------------------------------------------------------------------
  209. void CPwsDoc::AssertValid() const
  210. {
  211. CDocument::AssertValid();
  212. }
  213. //------------------------------------------------------------------
  214. void CPwsDoc::Dump(CDumpContext& dc) const
  215. {
  216. CDocument::Dump(dc);
  217. }
  218. #endif //_DEBUG
  219. /////////////////////////////////////////////////////////////////////////////
  220. // Access to the server methods
  221. //------------------------------------------------------------------
  222. // initialize the location of the server - it is stored in the registry
  223. BOOL CPwsDoc::FInitServerInfo()
  224. {
  225. DWORD err;
  226. HKEY hKey;
  227. DWORD iType = REG_SZ;
  228. DWORD cbPath = MAX_PATH+1;
  229. LPTSTR pPath;
  230. // open the registry key, if it exists
  231. err = RegOpenKeyEx(
  232. HKEY_LOCAL_MACHINE, // handle of open key
  233. REG_INSTALL_PATH, // address of name of subkey to open
  234. 0, // reserved
  235. KEY_READ, // security access mask
  236. &hKey // address of handle of open key
  237. );
  238. // if we were not able to open the key, then there was an error in the installation
  239. if ( err != ERROR_SUCCESS )
  240. {
  241. AfxMessageBox( IDS_INSTALL_ERROR );
  242. return FALSE;
  243. }
  244. // set up the buffer
  245. pPath = m_szServerPath.GetBuffer( cbPath );
  246. // get the base installation path for the server executable
  247. err = RegQueryValueEx( hKey, REG_PATH_VAL, NULL, &iType, (PUCHAR)pPath, &cbPath );
  248. // release the name buffers
  249. m_szServerPath.ReleaseBuffer();
  250. // all done, close the key before leaving
  251. RegCloseKey( hKey );
  252. // check the error code and fail if necessary
  253. if ( err != ERROR_SUCCESS )
  254. AfxMessageBox( IDS_INSTALL_ERROR );
  255. // return success
  256. return (err == ERROR_SUCCESS);
  257. }
  258. //------------------------------------------------------------------
  259. // updates the state of the server. Affects both the status strings and the
  260. // avis. Can be called from either a change notify or OnIdle.
  261. void CPwsDoc::UpdateServerState()
  262. {
  263. }
  264. //------------------------------------------------------------------
  265. BOOL CPwsDoc::LauchAppIfNecessary()
  266. {
  267. BOOL f;
  268. STARTUPINFO startupInfo;
  269. PROCESS_INFORMATION processInfo;
  270. TCHAR path[MAX_PATH+1];
  271. // if this is running under NT, skip this part
  272. OSVERSIONINFO osver;
  273. osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  274. GetVersionEx( &osver );
  275. if ( osver.dwPlatformId == VER_PLATFORM_WIN32_NT )
  276. return TRUE;
  277. // if the window is there, the exe is running and we don't have to do anything
  278. if ( FindWindow(SERVER_WINDOWCLASS_NAME, NULL) )
  279. return TRUE;
  280. CString szExeName;
  281. szExeName.LoadString( IDS_EXECUTABLE );
  282. ZeroMemory(&startupInfo,sizeof(STARTUPINFO));
  283. startupInfo.cb = sizeof(STARTUPINFO);
  284. CString szAppl;
  285. szAppl.LoadString( IDS_INETINFO_EXE );
  286. _tcscpy(path, m_szServerPath);
  287. _tcscat(path, _T("\\"));
  288. _tcscat(path, szAppl);
  289. //
  290. // the app is not running. Attempt to start the executable
  291. //
  292. f = CreateProcess(
  293. (LPCTSTR)path,
  294. (LPTSTR)(LPCTSTR)szExeName,
  295. NULL,
  296. NULL,
  297. FALSE,
  298. 0,
  299. NULL,
  300. NULL,
  301. &startupInfo,
  302. &processInfo
  303. );
  304. if ( !f )
  305. {
  306. AfxMessageBox( IDS_ERROR_START );
  307. // failure
  308. return FALSE;
  309. }
  310. // success
  311. return TRUE;
  312. }
  313. //------------------------------------------------------------------
  314. void CPwsDoc::PerformAction( DWORD action, DWORD expected )
  315. {
  316. }
  317. //------------------------------------------------------------------
  318. // if the service is running, stop it. If it is stopped, start it
  319. void CPwsDoc::ToggleService()
  320. {
  321. }
  322. /////////////////////////////////////////////////////////////////////////////
  323. // CPwsDoc commands
  324. //------------------------------------------------------------------
  325. void CPwsDoc::OnUpdateShowTips(CCmdUI* pCmdUI)
  326. {
  327. pCmdUI->Enable( TRUE );
  328. }
  329. //------------------------------------------------------------------
  330. void CPwsDoc::OnUpdateStart(CCmdUI* pCmdUI)
  331. {
  332. CW3ServerControl serverController;
  333. DWORD dwState = serverController.GetServerState();
  334. pCmdUI->Enable( dwState == MD_SERVER_STATE_STOPPED );
  335. }
  336. //------------------------------------------------------------------
  337. void CPwsDoc::OnUpdateStop(CCmdUI* pCmdUI)
  338. {
  339. CW3ServerControl serverController;
  340. DWORD dwState = serverController.GetServerState();
  341. pCmdUI->Enable( (dwState == MD_SERVER_STATE_STARTED) ||
  342. (dwState == MD_SERVER_STATE_PAUSED) );
  343. }
  344. //------------------------------------------------------------------
  345. void CPwsDoc::OnUpdatePause(CCmdUI* pCmdUI)
  346. {
  347. CW3ServerControl serverController;
  348. DWORD dwState = serverController.GetServerState();
  349. pCmdUI->Enable( dwState == MD_SERVER_STATE_STARTED );
  350. }
  351. //------------------------------------------------------------------
  352. void CPwsDoc::OnUpdateContinue(CCmdUI* pCmdUI)
  353. {
  354. CW3ServerControl serverController;
  355. DWORD dwState = serverController.GetServerState();
  356. pCmdUI->Enable( dwState == MD_SERVER_STATE_PAUSED );
  357. }
  358. //------------------------------------------------------------------
  359. void CPwsDoc::OnStart()
  360. {
  361. CW3ServerControl serverController;
  362. serverController.StartServer();
  363. }
  364. //------------------------------------------------------------------
  365. void CPwsDoc::OnStop()
  366. {
  367. CW3ServerControl serverController;
  368. serverController.StopServer();
  369. // if this is win95 and the main pane is showing, tell it to update
  370. if ( !m_fIsWinNT && g_FormMain )
  371. g_FormMain->UpdateServerState();
  372. }
  373. //------------------------------------------------------------------
  374. void CPwsDoc::OnPause()
  375. {
  376. CW3ServerControl serverController;
  377. serverController.PauseServer();
  378. }
  379. //------------------------------------------------------------------
  380. void CPwsDoc::OnContinue()
  381. {
  382. CW3ServerControl serverController;
  383. serverController.ContinueServer();
  384. }
  385. //------------------------------------------------------------------
  386. void CPwsDoc::OnShowTips()
  387. {
  388. CTipDlg dlg;
  389. dlg.DoModal();
  390. }
  391. /*
  392. //------------------------------------------------------------------
  393. void CPwsDoc::OnHelpFinder()
  394. {
  395. DWORD err;
  396. // build the path to the help file
  397. CString szPath;
  398. szPath.LoadString( IDS_HELP_LOC );
  399. szPath = m_szServerPath + szPath;
  400. // use shellexecute to open the file
  401. ShellExecute( NULL, NULL, (PCHAR)(LPCSTR)szPath, NULL, NULL, SW_SHOW );
  402. err = GetLastError();
  403. if ( err )
  404. {
  405. // just re-use szPath
  406. szPath.LoadString(IDS_NO_HELP);
  407. szPath.Format( "%s\nError = %d", szPath, err );
  408. AfxMessageBox( szPath );
  409. }
  410. }
  411. */
  412. //------------------------------------------------------------------
  413. void CPwsDoc::OnHelpDocumentation()
  414. {
  415. // this documentation only works if it is served. Thus, if the local
  416. // server is not running, we should tell that to the user.
  417. CW3ServerControl serverController;
  418. if ( g_fShutdownMode || (serverController.GetServerState() != MD_SERVER_STATE_STARTED) )
  419. {
  420. AfxMessageBox( IDS_HELPERR_REQUIRES_SERVER );
  421. return;
  422. }
  423. // load the served help docs url
  424. CString szHelpURL;
  425. szHelpURL.LoadString( IDS_HELPLOC_DOCS );
  426. // use shellexecute to access the help via the browser
  427. ShellExecute(
  428. NULL, // handle to parent window
  429. NULL, // pointer to string that specifies operation to perform
  430. szHelpURL, // pointer to filename or folder name string
  431. NULL, // pointer to string that specifies executable-file parameters
  432. NULL, // pointer to string that specifies default directory
  433. SW_SHOW // whether file is shown when opened
  434. );
  435. }
  436. //------------------------------------------------------------------
  437. void CPwsDoc::OnHelpHelpTroubleshooting()
  438. {
  439. // load the relative file path for the troublshooting
  440. CString szTroublePath;
  441. szTroublePath.LoadString( IDS_HELPLOC_README );
  442. // expand the path
  443. CString szExpandedPath;
  444. ExpandEnvironmentStrings(
  445. szTroublePath, // pointer to string with environment variables
  446. szExpandedPath.GetBuffer(MAX_PATH + 1), // pointer to string with expanded environment variables
  447. MAX_PATH // maximum characters in expanded string
  448. );
  449. szExpandedPath.ReleaseBuffer();
  450. // use shellexecute to access the help via the browser
  451. ShellExecute(
  452. NULL, // handle to parent window
  453. NULL, // pointer to string that specifies operation to perform
  454. szExpandedPath, // pointer to filename or folder name string
  455. NULL, // pointer to string that specifies executable-file parameters
  456. NULL, // pointer to string that specifies default directory
  457. SW_SHOW // whether file is shown when opened
  458. );
  459. }
  460. //------------------------------------------------------------------
  461. void CPwsDoc::OnUpdateTrayicon(CCmdUI* pCmdUI)
  462. {
  463. // if the exe is available, show the right thing
  464. if ( m_fIsPWSTrayAvailable )
  465. {
  466. pCmdUI->Enable( TRUE );
  467. pCmdUI->SetCheck( (::FindWindow(PWS_TRAY_WINDOW_CLASS,NULL) != NULL) );
  468. }
  469. else
  470. {
  471. pCmdUI->Enable( FALSE );
  472. pCmdUI->SetCheck( FALSE );
  473. }
  474. }
  475. //------------------------------------------------------------------
  476. void CPwsDoc::OnTrayicon()
  477. {
  478. HWND hwndTray = FindWindow(PWS_TRAY_WINDOW_CLASS,NULL);
  479. CString sz;
  480. // first, act directly on the application
  481. if ( hwndTray != NULL )
  482. {
  483. PostMessage( hwndTray, WM_CLOSE, 0, 0 );
  484. // make sure it doesn't start up again
  485. }
  486. // else start it up
  487. else
  488. {
  489. if ( GetPWSTrayPath( sz ) )
  490. {
  491. ShellExecute(
  492. NULL, // handle to parent window
  493. NULL, // pointer to string that specifies operation to perform
  494. sz, // pointer to filename or folder name string
  495. NULL, // pointer to string that specifies executable-file parameters
  496. NULL, // pointer to string that specifies default directory
  497. 0 // whether file is shown when opened
  498. );
  499. }
  500. // make sure it starts up again
  501. }
  502. // now write the proper value to the registry so that pwstray does, or doesn't
  503. // get launched the next time you log on to the system
  504. sz.LoadString( IDS_PWSTRAY_EXE );
  505. DWORD err;
  506. HKEY hKey;
  507. DWORD cbdata = sizeof(TCHAR) * (sz.GetLength() + 1);
  508. // open the registry key, if it exists
  509. err = RegOpenKeyEx(
  510. HKEY_LOCAL_MACHINE, // handle of open key
  511. SZ_KEY_RUN_TRAY, // address of name of subkey to open
  512. 0, // reserved
  513. KEY_WRITE, // security access mask
  514. &hKey // address of handle of open key
  515. );
  516. // if we did not open the key for any reason (say... it doesn't exist)
  517. // then show the icon
  518. if ( err != ERROR_SUCCESS )
  519. return;
  520. //do the right thing
  521. if ( hwndTray )
  522. {
  523. // remove it
  524. err = RegDeleteValue(
  525. hKey, // handle of key
  526. SZ_KEY_RUN_VALUE // address of value name
  527. );
  528. }
  529. else
  530. {
  531. // add it
  532. err = RegSetValueEx(
  533. hKey, // handle of key to query
  534. SZ_KEY_RUN_VALUE, // address of name of value to query
  535. 0, // reserved
  536. REG_SZ, // address of buffer for value type
  537. (LPBYTE)(LPCTSTR)sz, // address of data buffer
  538. cbdata // address of data buffer size
  539. );
  540. }
  541. // all done, close the key before leaving
  542. RegCloseKey( hKey );
  543. }
  544. //------------------------------------------------------------------
  545. BOOL CPwsDoc::GetPWSTrayPath( CString &sz )
  546. {
  547. if ( !GetSystemDirectory(sz.GetBuffer(MAX_PATH+1),MAX_PATH) )
  548. return FALSE;
  549. sz.ReleaseBuffer();
  550. // add on the executable part
  551. CString szExe;
  552. szExe.LoadString( IDS_PWSTRAY_EXE );
  553. sz += '\\';
  554. sz += szExe;
  555. return TRUE;
  556. }