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.

597 lines
18 KiB

  1. // pws.cpp : Defines the class behaviors for the application.
  2. //
  3. #include "stdafx.h"
  4. #include "pwsform.h"
  5. #include "resource.h"
  6. #include "Title.h"
  7. #include "FormIE.h"
  8. #include "MainFrm.h"
  9. #include "pwsDoc.h"
  10. #include "PWSChart.h"
  11. #include "SelBarFm.h"
  12. #include "ServCntr.h"
  13. #include <winsock2.h>
  14. #include "TipDlg.h"
  15. #include "pwsctrl.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. #define CMD_START _T("start")
  22. #define CMD_STOP _T("stop")
  23. #define CMD_OPEN _T("open:")
  24. #define CMD_OPEN_MAIN _T("main")
  25. #define CMD_OPEN_ADV _T("advanced")
  26. #define CMD_OPEN_TOUR _T("tour")
  27. //#define CMD_OPEN_WEBSITE _T("website")
  28. //#define CMD_OPEN_PUBWIZ _T("pubwiz")
  29. #define CMD_SEPS _T("/- ")
  30. #define FILES_QUERY_STRING _T("?dropStr=");
  31. // globals
  32. //extern CPwsForm* g_p_FormView;
  33. extern CPwsDoc* g_p_Doc;
  34. CString g_szHelpLocation;
  35. WORD g_InitialPane = PANE_MAIN;
  36. WORD g_InitialIELocation = INIT_IE_TOUR;
  37. CString g_AdditionalIEURL;
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CPwsApp
  40. BEGIN_MESSAGE_MAP(CPwsApp, CWinApp)
  41. //{{AFX_MSG_MAP(CPwsApp)
  42. ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
  43. //}}AFX_MSG_MAP
  44. // Standard file based document commands
  45. ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
  46. ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
  47. END_MESSAGE_MAP()
  48. /////////////////////////////////////////////////////////////////////////////
  49. // CPwsApp construction
  50. //-----------------------------------------------------
  51. CPwsApp::CPwsApp() :
  52. m_fShowedStartupTips( FALSE )
  53. {
  54. }
  55. //-----------------------------------------------------
  56. CPwsApp::~CPwsApp()
  57. {
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. // The one and only CPwsApp object
  61. CPwsApp theApp;
  62. static const CLSID clsid =
  63. { 0x35c43df, 0x8464, 0x11d0, { 0xa9, 0x2d, 0x8, 0x0, 0x2b, 0x2c, 0x6f, 0x32 } };
  64. /////////////////////////////////////////////////////////////////////////////
  65. // CPwsApp initialization
  66. //-----------------------------------------------------
  67. // return FALSE to continue running the application
  68. BOOL CPwsApp::DealWithParameters()
  69. {
  70. BOOL fAnswer = FALSE;
  71. // under windows NT, we always just invoke the UI, no matter what the command line
  72. OSVERSIONINFO info_os;
  73. info_os.dwOSVersionInfoSize = sizeof(info_os);
  74. // check what sort of operating system we are running on
  75. if ( !GetVersionEx( &info_os ) )
  76. return FALSE;
  77. CString sz = m_lpCmdLine;
  78. sz.TrimRight();
  79. // the first one is easy. If there is no command line, invoke the UI and leave
  80. if ( sz.IsEmpty() )
  81. return FALSE;
  82. /* The publishing wizard has been pulled from PWS for NT5
  83. // The next one is also easy. If there is no '/' character, then the
  84. // parameters have to be file names for the publishing wizard. Also, the OS
  85. // gets rid of any spaces in the filenames for us. So we can just replace
  86. // them with ';' characters and be done with it
  87. if ( sz.Find(_T('/')) < 0 )
  88. {
  89. // set up to go to the publishing wizard
  90. g_InitialPane = PANE_IE;
  91. g_InitialIELocation = INIT_IE_PUBWIZ;
  92. // build the additional string
  93. g_AdditionalIEURL = FILES_QUERY_STRING; // ?dropStr=
  94. // at this point it is desirous to convert the files listed in szAdditional,
  95. // which are in 8.3 format into long file names format. This means that they
  96. // will have to be put in quotes to handle spaces in the names. If a name
  97. // is already in quotes, then do not act on it in this way. Just add it to the
  98. // list as it is.
  99. CString szShortNames = sz;
  100. CString szTemp, szTemp2;
  101. BOOL fFoundOneFile = FALSE;
  102. // trim any trailing whitespace
  103. szShortNames.TrimRight();
  104. // loop through all the files
  105. while( szShortNames.GetLength() )
  106. {
  107. // trim any leading whitespace characters
  108. szShortNames.TrimLeft();
  109. // if the name is already in quotes, just add it
  110. if ( szShortNames[0] == _T('\"') )
  111. {
  112. // find the closing quote
  113. szShortNames = szShortNames.Right( szShortNames.GetLength() - 1 );
  114. int ichClose = szShortNames.Find(_T('\"'));
  115. // build the name
  116. szTemp = _T('\"');
  117. // if there was no closing quote use the whole string
  118. if ( ichClose < 0 )
  119. {
  120. szTemp += szShortNames;
  121. szShortNames.Empty();
  122. // close the qoutes
  123. szTemp += _T('\"');
  124. }
  125. else
  126. {
  127. szTemp += szShortNames.Left(ichClose+1);
  128. // get this file name out of the szShortNames path so we don't do it again
  129. szShortNames = szShortNames.Right(szShortNames.GetLength() - (ichClose+1));
  130. }
  131. }
  132. else
  133. // it is an 8.3 name, convert it
  134. {
  135. // find the space (could do inline, but this is faster)
  136. int ichSpace = szShortNames.Find(_T(' '));
  137. // get just the one file name
  138. if ( ichSpace > 0 )
  139. szTemp = szShortNames.Left(ichSpace);
  140. else
  141. szTemp = szShortNames;
  142. // prep the find file info block
  143. HANDLE hFindFile;
  144. WIN32_FIND_DATA findData;
  145. ZeroMemory( &findData, sizeof(findData) );
  146. // find the file
  147. hFindFile = FindFirstFile(
  148. (LPCTSTR)szTemp, // pointer to name of file to search for
  149. &findData // pointer to returned information
  150. );
  151. // if it was successful, extract the long file name
  152. if ( hFindFile != INVALID_HANDLE_VALUE )
  153. {
  154. // enclose the path in quotes and go
  155. szTemp = _T('\"');
  156. // start by adding the path portion of the original string
  157. if ( ichSpace >= 0 )
  158. szTemp += szShortNames.Left(ichSpace);
  159. else
  160. szTemp += szShortNames;
  161. // chop off the file name - but leave the trailing '\' character
  162. if ( szTemp.ReverseFind(_T('\\')) > 0 )
  163. szTemp = szTemp.Left( szTemp.ReverseFind(_T('\\')) + 1 );
  164. // copy over the full path name
  165. szTemp += findData.cFileName;
  166. // close the qoutes
  167. szTemp += _T('\"');
  168. }
  169. // if there are no more names, then empth the path, otherwise, just shorten it
  170. if ( ichSpace < 0 )
  171. szShortNames.Empty();
  172. else
  173. // get this file name out of the szShortNames path so we don't do it again
  174. szShortNames = szShortNames.Right(szShortNames.GetLength() - ichSpace);
  175. // we aren't really finding files here, so just close the find handle
  176. FindClose( hFindFile );
  177. }
  178. // if we have already added a file, precede the one we are about to add with a ;
  179. if ( fFoundOneFile )
  180. g_AdditionalIEURL += _T(';');
  181. // add the string
  182. g_AdditionalIEURL += szTemp;
  183. fFoundOneFile = TRUE;
  184. }
  185. // prevent the tips dialog from coming up
  186. m_fShowedStartupTips = TRUE;
  187. // all done.
  188. return FALSE;
  189. }
  190. */
  191. // copy the command line into a buffer
  192. TCHAR buff[MAX_PATH];
  193. _tcscpy( buff, sz );
  194. // just so we don't do it in the loop, initialize the open: string
  195. // length variable
  196. DWORD cchOpen = _tcslen( CMD_OPEN );
  197. // parse out the arguments
  198. LPTSTR pTok;
  199. pTok = _tcstok( buff, CMD_SEPS );
  200. while ( pTok )
  201. {
  202. // the start and stop commands are for windows 95 only
  203. if ( info_os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
  204. {
  205. // look for the start command
  206. if ( _tcsicmp(pTok, CMD_START) == 0 )
  207. {
  208. W95StartW3SVC();
  209. fAnswer = TRUE;
  210. goto nextToken;
  211. }
  212. // look for the stop command
  213. if ( _tcsicmp(pTok, CMD_STOP) == 0 )
  214. {
  215. W95ShutdownW3SVC();
  216. W95ShutdownIISADMIN();
  217. fAnswer = TRUE;
  218. goto nextToken;
  219. }
  220. }
  221. // commands that work for all platforms
  222. // look for the open: command
  223. if ( _tcsnicmp(pTok, CMD_OPEN, cchOpen) == 0 )
  224. {
  225. // just put the open parameter in a string
  226. CString szOpen = pTok;
  227. szOpen = szOpen.Right( szOpen.GetLength() - cchOpen );
  228. // now test all the options
  229. if ( szOpen.CompareNoCase(CMD_OPEN_MAIN) == 0 )
  230. {
  231. g_InitialPane = PANE_MAIN;
  232. }
  233. else if ( szOpen.CompareNoCase(CMD_OPEN_ADV) == 0 )
  234. {
  235. g_InitialPane = PANE_ADVANCED;
  236. }
  237. else if ( szOpen.CompareNoCase(CMD_OPEN_TOUR) == 0 )
  238. {
  239. g_InitialPane = PANE_IE;
  240. g_InitialIELocation = INIT_IE_TOUR;
  241. }
  242. /*
  243. else if ( szOpen.CompareNoCase(CMD_OPEN_WEBSITE) == 0 )
  244. {
  245. g_InitialPane = PANE_IE;
  246. g_InitialIELocation = INIT_IE_WEBSITE;
  247. }
  248. else if ( szOpen.CompareNoCase(CMD_OPEN_PUBWIZ) == 0 )
  249. {
  250. g_InitialPane = PANE_IE;
  251. g_InitialIELocation = INIT_IE_PUBWIZ;
  252. // prevent the tips dialog from coming up
  253. m_fShowedStartupTips = TRUE;
  254. }
  255. */
  256. }
  257. // Get next token
  258. nextToken:
  259. pTok = _tcstok( NULL, CMD_SEPS );
  260. }
  261. return fAnswer;
  262. }
  263. //-----------------------------------------------------
  264. // In the event that another instance of this application is already
  265. // running, we not only need to activate it and bring it to the foreground,
  266. // but it should also handle the command line that was passed into this
  267. // instance. The use may have dragged files only the publishing wizard for
  268. // example and that should be sent to the publishing wizard.
  269. // pWnd is the window of the other instance that we are targeting. The command
  270. // line information has already been parsed and can be found the the globals
  271. // declared above.
  272. //
  273. // In order to pass the command information from this instance to the other
  274. // requires that we set up a shared memory structure. Then when we send the
  275. // message to the other instance, it can get it. Upon return, we no longer
  276. // need the shared memory, so we can clean it up.
  277. void CPwsApp::SendCommandInfo( CWnd* pWnd )
  278. {
  279. HANDLE hFileMap = NULL;
  280. PPWS_INSTANCE_TRANSFER pData = NULL;
  281. DWORD cbSharedSpace;
  282. // calculate how bit the shared space needs to be
  283. cbSharedSpace = sizeof(PWS_INSTANCE_TRANSFER);
  284. // add in enough to copy in the possibly wide character extra info string
  285. cbSharedSpace += (g_AdditionalIEURL.GetLength() + 1) * sizeof(WCHAR);
  286. // set up the shared memory space.
  287. hFileMap = CreateFileMapping(
  288. INVALID_HANDLE_VALUE,
  289. NULL,
  290. PAGE_READWRITE,
  291. 0,
  292. cbSharedSpace,
  293. PWS_INSTANCE_TRANSFER_SPACE_NAME
  294. );
  295. if ( hFileMap == NULL )
  296. return;
  297. pData = (PPWS_INSTANCE_TRANSFER)MapViewOfFile(
  298. hFileMap,
  299. FILE_MAP_ALL_ACCESS,
  300. 0,
  301. 0,
  302. cbSharedSpace
  303. );
  304. if ( pData == NULL )
  305. {
  306. CloseHandle(hFileMap);
  307. return;
  308. }
  309. // blank it all out
  310. ZeroMemory( pData, cbSharedSpace );
  311. // copy in the parsed command line data
  312. pData->iTargetPane = g_InitialPane;
  313. pData->iTargetIELocation = g_InitialIELocation;
  314. _tcscpy( &pData->tchIEURL, (LPCTSTR)g_AdditionalIEURL );
  315. // send the message
  316. pWnd->SendMessage( WM_PROCESS_REMOTE_COMMAND_INFO );
  317. // clean up the shared memory
  318. UnmapViewOfFile( pData );
  319. CloseHandle(hFileMap);
  320. }
  321. //-----------------------------------------------------
  322. BOOL CPwsApp::InitInstance()
  323. {
  324. BOOL fLeaveEarly = FALSE;
  325. // if there were options passed in to the command line, act on them without bringing
  326. // up any windows or anything
  327. if ( m_lpCmdLine[0] )
  328. {
  329. if ( DealWithParameters() )
  330. return FALSE;
  331. }
  332. // no parameters (or this is NT) - run normally
  333. CString sz;
  334. sz.LoadString( IDR_MAINFRAME );
  335. sz = sz.Left( sz.Find('\n') );
  336. // initialize the windows sockets layer
  337. WSADATA wsaData;
  338. INT err = WSAStartup(MAKEWORD(2,0), &wsaData);
  339. // see if another instance of this application is running
  340. CWnd* pPrevWind = CWnd::FindWindow( NULL, sz );
  341. if ( pPrevWind )
  342. {
  343. // pws is already running. Activate the previous one and quit
  344. pPrevWind->SetForegroundWindow();
  345. pPrevWind->ShowWindow(SW_RESTORE);
  346. // tell it to handle the command line information
  347. SendCommandInfo( pPrevWind );
  348. return FALSE;
  349. }
  350. // Initialize OLE libraries
  351. if (!AfxOleInit())
  352. {
  353. AfxMessageBox(IDP_OLE_INIT_FAILED);
  354. return FALSE;
  355. }
  356. // initialize the metabase interface
  357. if ( !FInitMetabaseWrapper(NULL) )
  358. return FALSE;
  359. AfxEnableControlContainer();
  360. // Standard initialization
  361. //#ifdef _AFXDLL
  362. Enable3dControls(); // Call this when using MFC in a shared DLL
  363. //#else
  364. // Enable3dControlsStatic(); // Call this when linking to MFC statically
  365. //#endif
  366. LoadStdProfileSettings(); // Load standard INI file options (including MRU)
  367. // Register document templates
  368. CSingleDocTemplate* pDocTemplate;
  369. pDocTemplate = new CSingleDocTemplate(
  370. IDR_MAINFRAME,
  371. RUNTIME_CLASS(CPwsDoc),
  372. RUNTIME_CLASS(CMainFrame), // main SDI frame window
  373. RUNTIME_CLASS(CFormSelectionBar));
  374. AddDocTemplate(pDocTemplate);
  375. m_server.ConnectTemplate(clsid, pDocTemplate, TRUE);
  376. // Parse command line for standard shell commands, DDE, file open
  377. CCommandLineInfo cmdInfo;
  378. ParseCommandLine(cmdInfo);
  379. if (cmdInfo.m_bRunEmbedded || cmdInfo.m_bRunAutomated)
  380. {
  381. COleTemplateServer::RegisterAll();
  382. // Application was run with /Embedding or /Automation. Don't show the
  383. // main window in this case.
  384. return TRUE;
  385. }
  386. m_server.UpdateRegistry(OAT_DISPATCH_OBJECT);
  387. COleObjectFactory::UpdateRegistryAll();
  388. // Dispatch commands specified on the command line
  389. if (!ProcessShellCommand(cmdInfo))
  390. return FALSE;
  391. // finally, we need to redirect the winhelp file location to something more desirable
  392. sz.LoadString( IDS_HELPLOC_PWSHELP );
  393. // expand the path
  394. ExpandEnvironmentStrings(
  395. sz, // pointer to string with environment variables
  396. g_szHelpLocation.GetBuffer(MAX_PATH + 1), // pointer to string with expanded environment variables
  397. MAX_PATH // maximum characters in expanded string
  398. );
  399. g_szHelpLocation.ReleaseBuffer();
  400. // free the existing path, and copy in the new one
  401. free((void*)m_pszHelpFilePath);
  402. m_pszHelpFilePath = _tcsdup(g_szHelpLocation);
  403. // set the name of the application correctly
  404. sz.LoadString( IDR_MAINFRAME );
  405. // cut it off so it is just the app name
  406. sz = sz.Left( sz.Find(_T('\n')) );
  407. // free the existing name, and copy in the new one
  408. free((void*)m_pszAppName);
  409. m_pszAppName = _tcsdup(sz);
  410. return TRUE;
  411. }
  412. //------------------------------------------------------------------
  413. void CPwsApp::OnFinalRelease()
  414. {
  415. FCloseMetabaseWrapper();
  416. WSACleanup();
  417. CWinApp::OnFinalRelease();
  418. }
  419. //------------------------------------------------------------------
  420. void CPwsApp::ShowTipsAtStartup()
  421. {
  422. m_fShowedStartupTips = TRUE;
  423. // show the tips tdialog - if requested
  424. CTipDlg dlg;
  425. if ( dlg.FShowAtStartup() )
  426. dlg.DoModal();
  427. }
  428. /////////////////////////////////////////////////////////////////////////////
  429. // CAboutDlg dialog used for App About
  430. class CAboutDlg : public CDialog
  431. {
  432. public:
  433. CAboutDlg();
  434. // Dialog Data
  435. //{{AFX_DATA(CAboutDlg)
  436. enum { IDD = IDD_ABOUTBOX };
  437. //}}AFX_DATA
  438. // ClassWizard generated virtual function overrides
  439. //{{AFX_VIRTUAL(CAboutDlg)
  440. protected:
  441. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  442. //}}AFX_VIRTUAL
  443. // Implementation
  444. protected:
  445. //{{AFX_MSG(CAboutDlg)
  446. // No message handlers
  447. //}}AFX_MSG
  448. DECLARE_MESSAGE_MAP()
  449. };
  450. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  451. {
  452. //{{AFX_DATA_INIT(CAboutDlg)
  453. //}}AFX_DATA_INIT
  454. }
  455. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  456. {
  457. CDialog::DoDataExchange(pDX);
  458. //{{AFX_DATA_MAP(CAboutDlg)
  459. //}}AFX_DATA_MAP
  460. }
  461. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  462. //{{AFX_MSG_MAP(CAboutDlg)
  463. //}}AFX_MSG_MAP
  464. END_MESSAGE_MAP()
  465. //------------------------------------------------------------------
  466. // App command to run the dialog
  467. void CPwsApp::OnAppAbout()
  468. {
  469. // load the about strings
  470. CString szAbout1;
  471. CString szAbout2;
  472. szAbout1.LoadString(IDS_ABOUT_MAIN);
  473. szAbout2.LoadString(IDS_ABOUT_SECONDARY);
  474. // run the shell about dialog
  475. ShellAbout( AfxGetMainWnd()->GetSafeHwnd(), szAbout1,szAbout2, LoadIcon(IDR_MAINFRAME) );
  476. }
  477. /////////////////////////////////////////////////////////////////////////////
  478. // CPwsApp commands
  479. //------------------------------------------------------------------
  480. BOOL CPwsApp::OnIdle(LONG lCount)
  481. {
  482. // if this is the startup - show the tips
  483. if ( !m_fShowedStartupTips )
  484. ShowTipsAtStartup();
  485. return FALSE;
  486. }