home *** CD-ROM | disk | FTP | other *** search
/ Enter 1999 November / ENTER11_1.bin / WARSZTAT / SDKJava32.exe / data1.cab / fg_Samples / Samples / Native / JView / jview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-17  |  70.8 KB  |  2,446 lines

  1. /*++
  2.  
  3. (C) Copyright 1995 - 1999 Microsoft Corporation.  All rights reserved.
  4.  
  5. Module Name:
  6.  
  7.     jview.cpp
  8.  
  9. Abstract:
  10.  
  11.     Front end to the Java virtual machine.
  12.  
  13. --*/
  14.  
  15. #pragma hdrstop
  16.  
  17. #define INITGUID 1
  18.  
  19. #include "jview.h"
  20. #include "cresprop.hpp"
  21. #include "version.h"
  22.  
  23.  
  24. #ifdef PROFILER_HOOK
  25.  
  26. #include <initguid.h>
  27. #include "jviewprf.h"
  28.  
  29. DEFINE_GUID(CLSID_JVIEWEventMonitor, 0x68c267c0, 0xb042, 0x11d2, 0xb0, 0x81, 0x0, 0x60, 0x8, 0x3, 0x9b, 0xf0);
  30. #define CLSIDSTR_JVIEWEventMonitor "{68C267C0-B042-11d2-B081-006008039BF0}"
  31.  
  32. #endif
  33.  
  34.  
  35. #define VER_LAST_COPYRIGHT_YEAR         1999
  36.  
  37.  
  38. // Macros
  39.  
  40. #define WIN32_ERROR_TO_HRESULT(err)    MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, (err))
  41.  
  42. #define WIN32_RESULT_TO_HRESULT(err)   ((err) == ERROR_SUCCESS ? S_OK : WIN32_ERROR_TO_HRESULT(err))
  43.  
  44. #define LAST_WIN32_ERROR_TO_HRESULT()  WIN32_RESULT_TO_HRESULT(GetLastError())
  45.  
  46. // e.g., "D2029F40-8AB3-11CF-85FB-00401C608501"
  47. // (+ 1) for null terminator
  48. #define GUIDSTR_LEN     (8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1)
  49.  
  50. // e.g., "{D2029F40-8AB3-11CF-85FB-00401C608501}"
  51. // (+ 1) for leading bracket, (+ 1) for trailing bracket
  52. #define GUIDSTR_MAX     (1 + GUIDSTR_LEN + 1)
  53.  
  54. #define MAX_BUFFER 4096
  55.  
  56. /* array element count */
  57.  
  58. #define ARRAY_ELEMENTS(rg)                (sizeof(rg) / sizeof((rg)[0]))
  59.  
  60.  
  61. #ifdef APPLETVIEWER
  62. #define APPLETVIEWER_CLASS L"com.ms.applet.Main"
  63. #else
  64. #define APPLETVIEWER_CLASS  "com.ms.applet.Main"
  65. #endif
  66.  
  67. RESOURCEJAVAPROPERTY g_AppletViewerProperties[] = {
  68.     L"com.ms.tools.appletviewer.warn.noappletattrs",    IDS_WARN_NOAPPLETATTRS,
  69.     L"com.ms.tools.appletviewer.warn.noparamattrs",     IDS_WARN_NOPARAMATTRS,
  70.     L"com.ms.tools.appletviewer.warn.invalidparam",     IDS_WARN_INVALIDPARAM,
  71.     L"com.ms.tools.appletviewer.warn.nocode",           IDS_WARN_NOCODE,
  72.     L"com.ms.tools.appletviewer.warn.parseerror",       IDS_WARN_PARSEERROR,
  73.     L"com.ms.tools.appletviewer.warn.noapphtml",        IDS_WARN_NOAPPLETTAGS,
  74.     L"com.ms.tools.appletviewer.warn.urlerror",         IDS_WARN_URLNOTFOUND,
  75.     L"com.ms.tools.appletviewer.warn.fileerror",        IDS_WARN_FILENOTFOUND,
  76.  
  77.     L"com.ms.tools.appletviewer.error.noapplets",       IDS_ERROR_NOAPPLETS,
  78.     L"com.ms.tools.appletviewer.error.unexpected",      IDS_ERROR_UNEXPECTED,
  79.  
  80.     L"com.ms.tools.appletviewer.menu.applet",           IDS_MENU_APPLET,
  81.     L"com.ms.tools.appletviewer.menu.reload",           IDS_MENU_RELOAD,
  82.     L"com.ms.tools.appletviewer.menu.restart",          IDS_MENU_RESTART,
  83.     L"com.ms.tools.appletviewer.menu.stop",             IDS_MENU_STOP,
  84.     L"com.ms.tools.appletviewer.menu.start",            IDS_MENU_START,
  85.     L"com.ms.tools.appletviewer.menu.html",             IDS_MENU_HTML,
  86.     L"com.ms.tools.appletviewer.menu.info",             IDS_MENU_INFO,
  87.     L"com.ms.tools.appletviewer.menu.console",          IDS_MENU_CONSOLE,
  88.     L"com.ms.tools.appletviewer.menu.secreload",        IDS_MENU_SECRELOAD,
  89.     L"com.ms.tools.appletviewer.menu.quit",             IDS_MENU_QUIT,
  90.  
  91.     L"com.ms.tools.appletviewer.usage",                 IDS_APPLETVIEWER_USAGE,
  92.     L"com.ms.tools.appletviewer.title",                 IDS_APPLETVIEWER_TITLE,
  93.     L"com.ms.tools.appletviewer.loading",               IDS_APPLETVIEWER_LOADING,
  94.     L"com.ms.tools.appletviewer.htmltitle",             IDS_APPLETVIEWER_HTMLTITLE,
  95.     L"com.ms.tools.appletviewer.infotitle",             IDS_APPLETVIEWER_INFOTITLE,
  96.     L"com.ms.tools.appletviewer.noinfo",                IDS_APPLETVIEWER_NOINFO,
  97. };
  98.  
  99. // Globals
  100.  
  101. BOOL  g_fPause       = FALSE;
  102. LPSTR g_pszMainClass = NULL;
  103.  
  104.  
  105. typedef int __cdecl snprintfProc (char *str, size_t count, const char *fmt, ...);
  106. typedef int __cdecl vsnprintfProc (char *str, size_t count, const char *fmt, va_list args);
  107.  
  108. int __cdecl unsafe_snprintf (char *str, size_t count, const char *fmt, ...)
  109. {
  110.     va_list va;
  111.     va_start(va, fmt);
  112.     int len = wvsprintf(str, fmt, va);
  113.     va_end(va);
  114.     return len;
  115. }
  116.  
  117. int __cdecl unsafe_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
  118. {
  119.     return wvsprintf(str, fmt, args);
  120. }
  121.  
  122. // Start with the unbounded versions in user32.  When msjava is loaded, we'll
  123. // switch to its bounded versions (jio_snprintf and jio_vsnprintf).
  124. snprintfProc  *g_pfnsnprintf  = &unsafe_snprintf;
  125. vsnprintfProc *g_pfnvsnprintf = &unsafe_vsnprintf;
  126.  
  127. #define JVIEWsnprintf  (*g_pfnsnprintf)
  128. #define JVIEWvsnprintf (*g_pfnvsnprintf)
  129.  
  130.  
  131. //------------------------------------------------------------------------
  132.  
  133.  
  134. BOOL WriteConsoleBasic (DWORD nStdHandle, LPCSTR lpBuffer, DWORD nNumberOfCharsToWrite);
  135. int LoadStringX (HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax);
  136.  
  137.  
  138. //------------------------------------------------------------------------
  139. // Exported profiler functions
  140.  
  141. #ifdef PROFILER_HOOK
  142.  
  143. BOOL  g_fMessageDisplayed = FALSE;
  144.  
  145. class JVIEWProfilerUtils : public IJVIEWProfilerUtils
  146. {
  147. public:
  148.  
  149.     STDMETHODIMP QueryInterface (REFIID riid, LPVOID *ppvObj)
  150.     {
  151.         if (   riid == IID_IUnknown
  152.             || riid == IID_IJVIEWProfilerUtils)
  153.         {
  154.             *ppvObj = (IJVIEWProfilerUtils*)this;
  155.         }
  156.         else
  157.         {
  158.             *ppvObj = NULL;
  159.             return E_NOINTERFACE;
  160.         }
  161.  
  162.         //AddRef();
  163.         return S_OK;
  164.     }
  165.  
  166.     STDMETHODIMP_(ULONG) AddRef ()
  167.     {
  168.         return 1;
  169.     }
  170.     
  171.     STDMETHODIMP_(ULONG) Release ()
  172.     {
  173.         return 1;
  174.     }
  175.  
  176.     STDMETHODIMP DisplayString (JVIEWDisplayClass cls, PCSTR pcsz)
  177.     {
  178.         BOOL ret;
  179.  
  180. #ifndef NO_CONSOLE
  181.         DWORD nhnd = STD_OUTPUT_HANDLE;
  182.  
  183.         if (cls == JDC_ERROR)
  184.             nhnd = STD_ERROR_HANDLE;
  185.  
  186.         ret = WriteConsoleBasic(nhnd, pcsz, -1);
  187.  
  188.         if (ret && cls == JDC_ERROR && g_fPause)
  189.             Pause();
  190. #else
  191.         UINT mbtype = MB_OK;
  192.  
  193.         switch (cls)
  194.         {
  195.         case JDC_INFORMATION:
  196.             mbtype |= MB_ICONINFORMATION;
  197.             break;
  198.  
  199.         case JDC_WARNING:
  200.             mbtype |= MB_ICONWARNING;
  201.             break;
  202.  
  203.         case JDC_ERROR:
  204.             mbtype |= MB_ICONERROR;
  205.             break;
  206.         }
  207.  
  208.         CHAR szTitle[MAX_BUFFER];
  209.         LoadStringX(NULL, IDS_WJVIEW_PROFTITLE, szTitle, sizeof(szTitle));
  210.  
  211.         ret = (MessageBox(NULL, pcsz, szTitle, mbtype) == IDOK);
  212. #endif
  213.  
  214.         if (ret)
  215.             g_fMessageDisplayed = TRUE;
  216.  
  217.         return ret ? S_OK : E_FAIL;
  218.     }
  219.  
  220.     STDMETHODIMP DisplayResourceString (JVIEWDisplayClass cls, HINSTANCE hinst, UINT id)
  221.     {
  222.         CHAR szText[BUFSIZE];
  223.         DWORD nChars;
  224.  
  225.         nChars = LoadStringX(hinst, id, szText, sizeof(szText));
  226.  
  227.         if (nChars)
  228.             return DisplayString(cls, szText);
  229.         else
  230.             return E_FAIL;
  231.     }
  232.  
  233.     STDMETHODIMP_(int) LoadResourceString (HINSTANCE hinst, UINT id, PSTR buf, int bufsize)
  234.     {
  235.         return LoadStringX(hinst, id, buf, bufsize);
  236.     }
  237.     
  238.     STDMETHODIMP_(int) snprintf (char *str, size_t count, const char *fmt, ...)
  239.     {
  240.         va_list va;
  241.         va_start(va, fmt);
  242.         int len = JVIEWvsnprintf(str, count, fmt, va);
  243.         va_end(va);
  244.         return len;
  245.     }
  246.  
  247.     STDMETHODIMP_(int) vsnprintf (char *str, size_t count, const char *fmt, va_list args)
  248.     {
  249.         return JVIEWvsnprintf(str, count, fmt, args);
  250.     }
  251. };
  252.  
  253. #endif // PROFILER_HOOK
  254.  
  255.  
  256. //------------------------------------------------------------------------
  257.  
  258.  
  259. #ifndef NO_CONSOLE
  260.  
  261. //------------------------------------------------------------------------------
  262. // WaitConsoleKeypress
  263. //
  264. // Waits for a keypress on the console.  Lightweight version of the CRT _getch
  265. // function, which this function is heavily based on.
  266. //------------------------------------------------------------------------------
  267.  
  268. VOID WaitConsoleKeypress()
  269. {
  270.     HANDLE hConsole;
  271.     DWORD OldConsoleMode;
  272.     INPUT_RECORD InputRecord;
  273.     DWORD NumberOfEventsRead;
  274.  
  275.     hConsole = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
  276.         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  277.  
  278.     if (hConsole != INVALID_HANDLE_VALUE) {
  279.  
  280.         //  Switch console to raw mode (no line input, no echo input).
  281.         GetConsoleMode(hConsole, &OldConsoleMode);
  282.         SetConsoleMode(hConsole, 0);
  283.  
  284.         while (TRUE) {
  285.  
  286.             if (!ReadConsoleInput(hConsole, &InputRecord, 1,
  287.                 &NumberOfEventsRead) || NumberOfEventsRead == 0)
  288.                 break;
  289.  
  290.             if (InputRecord.EventType == KEY_EVENT &&
  291.                 InputRecord.Event.KeyEvent.bKeyDown)
  292.             {
  293.                 switch (InputRecord.Event.KeyEvent.wVirtualKeyCode)
  294.                 {
  295.                 case VK_CONTROL:
  296.                 case VK_MENU:
  297.                     continue;
  298.  
  299.                 case 'c':
  300.                 case 'C':
  301.                     {
  302.                         DWORD dwCtrlKeysMask = (InputRecord.Event.KeyEvent.dwControlKeyState & (  LEFT_CTRL_PRESSED
  303.                                                                                                 | RIGHT_CTRL_PRESSED
  304.                                                                                                 | LEFT_ALT_PRESSED
  305.                                                                                                 | RIGHT_ALT_PRESSED
  306.                                                                                                 | SHIFT_PRESSED));
  307.                         if (   (dwCtrlKeysMask & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
  308.                             && !(dwCtrlKeysMask & ~(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
  309.                         {
  310.                             ExitProcess(-1);
  311.                         }
  312.                     }
  313.                     break;
  314.                 }
  315.  
  316.                 break;
  317.             }
  318.         }
  319.  
  320.         SetConsoleMode(hConsole, OldConsoleMode);
  321.         CloseHandle(hConsole);
  322.     }
  323. }
  324.  
  325. //------------------------------------------------------------------------------
  326. // WriteConsoleBasic
  327. //
  328. // Wrapper for the Win32 WriteConsole API.
  329. //------------------------------------------------------------------------------
  330.  
  331. BOOL WriteConsoleBasic(DWORD nStdHandle, LPCSTR lpBuffer, DWORD
  332.     nNumberOfCharsToWrite)
  333. {
  334.     DWORD NumberOfCharsWritten;
  335.  
  336.     if (nNumberOfCharsToWrite == (DWORD) -1)
  337.         nNumberOfCharsToWrite = lstrlen(lpBuffer);
  338.  
  339.     //  Don't call WriteConsoleA, because that won't handle the case of
  340.     //  redirected file handles on NT properly (jview does.not.exist >x 2>&1).
  341.     return WriteFile((HANDLE) nStdHandle, (LPSTR) lpBuffer,
  342.         nNumberOfCharsToWrite, &NumberOfCharsWritten, NULL);
  343. }
  344.  
  345. //------------------------------------------------------------------------------
  346. // WriteConsoleVprintf
  347. //
  348. // Wrapper for the Win32 WriteConsole API.
  349. //------------------------------------------------------------------------------
  350.  
  351. BOOL WriteConsoleVprintf(DWORD nStdHandle, LPCSTR lpFormat, va_list arglist)
  352. {
  353.     CHAR buffer[4096];
  354.     DWORD nChars;
  355.  
  356.     nChars = JVIEWvsnprintf(buffer, sizeof(buffer), lpFormat, arglist);
  357.  
  358.     return WriteConsoleBasic(nStdHandle, buffer, nChars);
  359. }
  360.  
  361. //------------------------------------------------------------------------------
  362. // WriteConsolePrintf
  363. //
  364. // Wrapper for the Win32 WriteConsole API.
  365. //------------------------------------------------------------------------------
  366.  
  367. BOOL WriteConsolePrintf(DWORD nStdHandle, LPCSTR lpFormat, ...)
  368. {
  369.     BOOL fResult;
  370.     va_list va;
  371.  
  372.     va_start(va, lpFormat);
  373.     fResult = WriteConsoleVprintf(nStdHandle, lpFormat, va);
  374.     va_end(va);
  375.  
  376.     return fResult;
  377. }
  378.  
  379. #endif // !NO_CONSOLE
  380.  
  381.  
  382. INT VMLoadString(
  383.     HINSTANCE hModule,
  384.     UINT      wStringID,
  385.     LPSTR     pszBuffer,
  386.     int       cchBufferMax,
  387.     WORD      wLanguage);
  388.  
  389. //------------------------------------------------------------------------------
  390. // LoadStringX
  391. //
  392. // Wrapper around VMLoadString that will use the default user language
  393. // to load strings.  For the console mode jview.exe, this wrapper will
  394. // also perform the converstion to the OEM character set.
  395. //------------------------------------------------------------------------------
  396.  
  397. int LoadStringX(
  398.     HINSTANCE hInstance, 
  399.     UINT      uID, 
  400.     LPSTR     lpBuffer,
  401.     int       nBufferMax)
  402. {
  403.     int nChars;
  404.  
  405.     nChars = VMLoadString(hInstance,uID,lpBuffer,nBufferMax,LANG_USER_DEFAULT);
  406.  
  407. #ifndef NO_CONSOLE
  408.  
  409.     if (nChars > 0)
  410.         CharToOem(lpBuffer, lpBuffer);
  411.  
  412. #endif
  413.  
  414.     return nChars;
  415. }
  416.  
  417. #ifdef NO_CONSOLE
  418. #define CharToOemX(args)    ((void) 0)
  419. #else
  420. #define CharToOemX(args)    CharToOem args
  421. #endif
  422.  
  423. //------------------------------------------------------------------------------
  424. // FatalError:
  425. //
  426. // Print a formatted error message to stderr
  427. //
  428. // Returns: Nothing
  429. //------------------------------------------------------------------------------
  430.  
  431. void FatalError
  432. (
  433.     INT idString,
  434.     ...
  435. )
  436. {
  437.     CHAR  szError[MAX_BUFFER];
  438.  
  439.     CHAR *pch;
  440.     CHAR  szFmt[BUFSIZE];
  441.     va_list va;
  442.  
  443.     // Load the prefix string into our buffer.
  444.     LoadStringX(NULL,IDS_ERROR,szError,sizeof(szError));
  445.  
  446.     // If an resource ID was specified load it up into a
  447.     // temp buffer so that we can use it from the printf
  448.     // operation.
  449.     if (idString)
  450.         LoadStringX(NULL, idString, szFmt, sizeof(szFmt));
  451.     else
  452.         lstrcpy(szFmt, "%s");
  453.  
  454.     // Get a pointer into our error buffer just past the
  455.     // prefix string.
  456.     pch = szError + lstrlen(szError);
  457.  
  458.     // Copy the remainder of the error message.  Reserve space for the '\n'
  459.     // we'll add below.
  460.     va_start(va, idString);
  461.     JVIEWvsnprintf(pch, sizeof(szError) - (pch-szError) - 1, szFmt, va);
  462.     va_end(va);
  463.  
  464.     // Terminate it.
  465.     lstrcat(szError,"\n");
  466.  
  467.     // If building for WJVIEW, display the error string in a
  468.     // MessageBox, otherwise dump it to the console.
  469.  
  470. #ifdef NO_CONSOLE
  471.     // Load up the caption title.  Reuse the printf format buffer.
  472.     LoadStringX(NULL,IDS_WJVIEW_TITLE_ERROR,szFmt,sizeof(szFmt));
  473.  
  474.     MessageBox(NULL,szError,szFmt,MB_OK|MB_ICONHAND);
  475. #else
  476.     WriteConsoleBasic(STD_ERROR_HANDLE,szError,lstrlen(szError));
  477.  
  478.     if (g_fPause)
  479.         Pause();
  480. #endif
  481.  
  482. }
  483.  
  484. //------------------------------------------------------------------------------
  485. // FatalErrorHR:
  486. //
  487. //      Print a formatted error followup by an hresult tp stderr
  488. //------------------------------------------------------------------------------
  489.  
  490. void FatalErrorHR
  491. (
  492.     HRESULT hr,
  493.     INT     idString,
  494.     ...
  495. )
  496. {
  497.     CHAR  szError[MAX_BUFFER] = "\0";
  498.     CHAR *pch                 = NULL;;
  499.     DWORD cRemaining          = sizeof(szError);
  500.  
  501.     CHAR  szFmt[BUFSIZE];
  502.     DWORD nChars;
  503.     DWORD res;
  504.     va_list va;
  505.  
  506.     // Load the error prefix string.
  507.     nChars = LoadStringX(NULL,IDS_ERROR,szError, sizeof(szError));
  508.  
  509.     // Keep track of our current position in the error string buffer.
  510.     cRemaining -= nChars;
  511.     pch         = szError + nChars;
  512.  
  513.     // Load next portion of the error string based upon the specified
  514.     // resource ID, and then do a printf operation into the error
  515.     // buffer using the resource string and the specified params.
  516.     nChars = LoadStringX(NULL, idString, szFmt, sizeof(szFmt));
  517.  
  518.     // Reserve 4 chars for the " : " and "\n" we may add below.
  519.     cRemaining = sizeof(szError) - nChars - 4;
  520.     
  521.     va_start(va, idString);
  522.     JVIEWvsnprintf(pch, cRemaining, szFmt, va);
  523.     va_end(va);
  524.  
  525.     // Add a seperator to the message.
  526.     lstrcat( szError, " : " );
  527.  
  528.     // Keep track of our current position in the error string buffer.
  529.     pch = szError + lstrlen(szError);
  530.     cRemaining = MAX_BUFFER - (pch - szError);
  531.  
  532.     // Add more text to the error buffer based upon the specified
  533.     // HRESULT.
  534.     res = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  535.                         NULL,
  536.                         (DWORD)hr,
  537.                         LOCALE_SYSTEM_DEFAULT,
  538.                         pch,
  539.                         cRemaining,
  540.                         NULL);
  541.  
  542.     if (!res)
  543.     {
  544.         // If not system error message was found for the specified
  545.         // HRESULT, use a generic error.
  546.  
  547.         CHAR szSCODE[BUFSIZE];
  548.  
  549.         LoadStringX(NULL, IDS_SCODE, szSCODE, sizeof(szSCODE));
  550.         JVIEWsnprintf(pch, cRemaining, szSCODE, (DWORD)hr);
  551.     }
  552.     else
  553.     {
  554.         // Convert ANSI string returned by FormatMessage to OEM.
  555.         CharToOemX((pch,pch));
  556.  
  557.         // Now we check if the error is "Member not found", and if it is, we
  558.         // will append some additional info to the error message letting
  559.         // the user know it was main() that could not be found, since that
  560.         // is the only time this message should be generated.
  561.         if (hr == DISP_E_MEMBERNOTFOUND)
  562.         {
  563.             lstrcat(szError,"\n");
  564.  
  565.             // Move pointer to the end of the buffer.
  566.             pch = szError + lstrlen(szError);
  567.  
  568.             LoadStringX(NULL,IDS_NOMAIN,szFmt,sizeof(szFmt));
  569.  
  570.             cRemaining = MAX_BUFFER - (pch - szError);
  571.             JVIEWsnprintf(pch, cRemaining, szFmt, g_pszMainClass, g_pszMainClass);
  572.         }
  573.     }
  574.  
  575.     // If building for WJVIEW, display the error string in a
  576.     // MessageBox, otherwise dump it to the console.
  577. #ifdef NO_CONSOLE
  578.     // Load up the caption title.  Reuse the printf format buffer.
  579.     LoadStringX(NULL,IDS_WJVIEW_TITLE_ERROR,szFmt,sizeof(szFmt));
  580.  
  581.     MessageBox(NULL,szError,szFmt,MB_OK|MB_ICONHAND);
  582. #else
  583.     WriteConsoleBasic(STD_ERROR_HANDLE,szError,lstrlen(szError));
  584.  
  585.     if (g_fPause)
  586.         Pause();
  587. #endif
  588. }
  589.  
  590.  
  591. #ifndef NO_CONSOLE
  592.  
  593. //------------------------------------------------------------------------------
  594. // Pause:
  595. //
  596. // -p was given on the command line, and we have an error, thus we display
  597. // amessage to the user to press a key to terminate JView, thus allowing enough
  598. // time to read the message before JView termnates and the console it was
  599. // running in goes away if being executed from the IDE
  600. //
  601. // Returns: Nothing
  602. //------------------------------------------------------------------------------
  603.  
  604. void Pause()
  605. {
  606.     CHAR szText[BUFSIZE];
  607.     DWORD nChars;
  608.  
  609.     nChars = LoadStringX(NULL, IDS_PRESSANYKEY, szText, sizeof(szText));
  610.     WriteConsoleBasic(STD_ERROR_HANDLE, szText, nChars);
  611.     WaitConsoleKeypress();
  612.     WriteConsoleBasic(STD_ERROR_HANDLE, "\n", 1);
  613. }
  614.  
  615. #endif
  616.  
  617.  
  618. //------------------------------------------------------------------------------
  619. // CJView::CJView:
  620. //    Constructor
  621. //------------------------------------------------------------------------------
  622. CJView::CJView (int ac, char **av) : m_ac (ac), m_av (av)
  623. {
  624.     m_fVerify                   = FALSE;
  625.     m_fVerboseStackTraces       = FALSE;
  626.     m_pszClassPath              = NULL;
  627.     m_pszAppend                 = NULL;
  628.     m_pszPrepend                = NULL;
  629.     m_pszClassName              = NULL;
  630.     m_ppszArgs                  = NULL;
  631.     m_iArgs                     = 0;
  632.     m_pJE                       = NULL;
  633.     m_pszNamespace              = NULL;
  634. #ifdef APPLETVIEWER
  635.     m_fApplet                   = TRUE;
  636. #else
  637.     m_pProperties               = NULL;
  638.     m_fApplet                   = FALSE;
  639. #endif
  640.  
  641. #ifdef PROFILER_HOOK
  642.     m_pProfiler                 = NULL;
  643.     m_fAttemptedLoadProfiler    = FALSE;
  644.     m_fEnableProfiling          = FALSE;
  645. #endif
  646. }
  647.  
  648. //------------------------------------------------------------------------------
  649. // CJView::~CJView:
  650. //    Destructor
  651. //------------------------------------------------------------------------------
  652. CJView::~CJView ()
  653. {
  654.     deleteSZ(m_pszClassPath);
  655.     deleteSZ(m_pszClassName);
  656.     deleteSZ(m_pszAppend);
  657.     deleteSZ(m_pszPrepend);
  658.     deleteSZ(m_pszNamespace);
  659.  
  660.     g_pszMainClass = NULL;
  661.  
  662.     if (m_ppszArgs)
  663.     {
  664.         INT n = 0;
  665.  
  666.         while (m_ppszArgs[n] != NULL)
  667.             delete [] m_ppszArgs[n++];
  668.         delete [] m_ppszArgs;
  669.     }
  670.  
  671. #ifndef APPLETVIEWER
  672.  
  673.     if (m_pProperties)
  674.     {
  675.         m_pProperties->Release();
  676.         m_pProperties = NULL;
  677.     }
  678.  
  679. #endif
  680.  
  681. #ifdef PROFILER_HOOK
  682.     if (m_pProfiler)
  683.         m_pProfiler->Release();
  684. #endif
  685.  
  686.     if (m_pJE)
  687.     {
  688.         m_pJE->Release();
  689.         CoUninitialize();
  690.     }
  691. }
  692.  
  693.  
  694. #ifdef PROFILER_HOOK
  695.  
  696. IJVIEWProfiler *CreateProfilerFromLibrary (PCSTR pcszProfilerLibFilename)
  697. {
  698.     IJVIEWProfiler *pProfiler = NULL;
  699.  
  700.     HMODULE hmodProfiler = LoadLibrary(pcszProfilerLibFilename);
  701.     if (hmodProfiler)
  702.     {
  703.         JVIEWPRF_CreateProfilerProc *pfnCreateProfiler = (JVIEWPRF_CreateProfilerProc*)GetProcAddress(
  704.                 hmodProfiler, JVIEWPRF_CreateProfilerProcNameStr);
  705.         if (pfnCreateProfiler)
  706.         {
  707.             pProfiler = (*pfnCreateProfiler)();
  708.         }
  709.  
  710.         if (!pProfiler)
  711.         {
  712.             LPFNGETCLASSOBJECT pfnDllGetClassObject = (LPFNGETCLASSOBJECT)GetProcAddress(
  713.                     hmodProfiler, "DllGetClassObject");
  714.             if (pfnDllGetClassObject)
  715.             {
  716.                 IClassFactory *pProfilerFactory;
  717.                 if (SUCCEEDED((*pfnDllGetClassObject)(CLSID_DefaultJVIEWProfiler, IID_IClassFactory, (PVOID*)&pProfilerFactory)))
  718.                 {
  719.                     pProfilerFactory->CreateInstance(NULL, IID_IJVIEWProfiler, (PVOID*)&pProfiler);
  720.                 
  721.                     pProfilerFactory->Release();
  722.                 }
  723.             }
  724.         }
  725.  
  726.         if (!pProfiler)
  727.         {
  728.             FreeLibrary(hmodProfiler);
  729.         }
  730.     }
  731.  
  732.     return pProfiler;
  733. }
  734.  
  735.  
  736. IJVIEWProfiler *CJView::LoadProfiler (BOOL fSilent)
  737. {
  738.     IJVIEWProfiler *pProfiler = m_pProfiler;
  739.  
  740.     if (!pProfiler && !m_fAttemptedLoadProfiler)
  741.     {
  742.         UINT idError = fSilent ? 0 : IDS_COULDNOTLOADPROF;
  743.  
  744.         CHAR szProfilerCLSID[GUIDSTR_MAX];
  745.         if (GetEnvironmentVariable(JVIEWPRF_ENV_VAR_CLSID_STR, szProfilerCLSID, sizeof(szProfilerCLSID)))
  746.         {
  747.             WCHAR wszProfilerCLSID[GUIDSTR_MAX*2];
  748.             for (unsigned i = 0; i < sizeof(szProfilerCLSID); i++)
  749.                 wszProfilerCLSID[i] = szProfilerCLSID[i];
  750.  
  751.             CLSID ProfilerCLSID;
  752.             if (SUCCEEDED(CLSIDFromString(wszProfilerCLSID, &ProfilerCLSID)))
  753.             {
  754.                 CoCreateInstance(ProfilerCLSID, NULL, CLSCTX_INPROC_SERVER, IID_IJVIEWProfiler, (PVOID*)&pProfiler);
  755.             }
  756.         }
  757.  
  758.         if (!pProfiler)
  759.         {
  760.             CHAR szProfilerLibFilename[MAX_PATH];
  761.             if (GetEnvironmentVariable(JVIEWPRF_ENV_VAR_LIB_STR, szProfilerLibFilename, sizeof(szProfilerLibFilename)))
  762.             {
  763.                 pProfiler = CreateProfilerFromLibrary(szProfilerLibFilename);
  764.             }
  765.         }
  766.  
  767.         if (!pProfiler)
  768.         {
  769.             pProfiler = CreateProfilerFromLibrary(JVIEWPRF_DEFAULT_LIB_FILENAME_STR);
  770.         }
  771.  
  772.         if (pProfiler)
  773.         {
  774.             JVIEWProfilerUtils *pUtils = new JVIEWProfilerUtils();
  775.             if (pUtils)
  776.             {
  777.                 DWORD flags = 0;
  778.                 if (SUCCEEDED(pProfiler->JVIEWInitialize(pUtils, &flags)))
  779.                 {
  780.                     m_fProfilerSupportsParameters = (flags & JVIEWPRF_INIT_SUPPORTS_PARAMS);
  781.                 }
  782.                 else
  783.                 {
  784.                     if (g_fMessageDisplayed)
  785.                         idError = 0;
  786.                     else
  787.                         idError = IDS_COULDNOTINITPROF;
  788.  
  789.                     pProfiler->Release();
  790.                     pProfiler = NULL;
  791.                 }
  792.  
  793.                 //pUtils->Release();
  794.             }
  795.             
  796.         }
  797.  
  798.         if (!pProfiler && idError)
  799.             FatalError(idError);
  800.  
  801.         m_pProfiler = pProfiler;
  802.         m_fAttemptedLoadProfiler = TRUE;
  803.     }
  804.  
  805.     return pProfiler;
  806. }
  807.  
  808.  
  809. BOOL CJView::ParseProfilingParams (PCSTR pcszParams)
  810. {
  811.     BOOL ret = FALSE;
  812.  
  813.     IJVIEWProfiler *pProfiler = LoadProfiler();
  814.     if (pProfiler)
  815.     {
  816.         if (pcszParams[0] == '\0')
  817.         {
  818.             ret = TRUE;
  819.         }
  820.         else if (!m_fProfilerSupportsParameters)
  821.         {
  822.             FatalError(IDS_NOPROFPARAMS);
  823.         }
  824.         else
  825.         {
  826.             pcszParams++;
  827.  
  828.             ret = SUCCEEDED(pProfiler->ParseParameters(pcszParams));
  829.  
  830.             if (!ret && !g_fMessageDisplayed)
  831.             {
  832.                 FatalError(IDS_BADPROFPARAMS);
  833.             }
  834.         }
  835.     }
  836.  
  837.     return ret;
  838. }
  839.  
  840. #endif // PROFILER_HOOK
  841.  
  842.  
  843. //------------------------------------------------------------------------------
  844. // CJView::m_InitComAndJava:
  845. //
  846. // Initializes COM and obtains the neccessary interfaces from the Java VM
  847. //
  848. // Returns: TRUE if successful, FALSE if not
  849. //------------------------------------------------------------------------------
  850. BOOL CJView::m_InitComAndJava ()
  851. {
  852.     HRESULT           hr   = E_UNEXPECTED;
  853.     IClassFactory    *pcf  = NULL;
  854.  
  855.     hr = CoInitialize(NULL);
  856.  
  857.     if (FAILED(hr))
  858.     {
  859.         FatalErrorHR(hr, IDS_COULDNOTINITOLE);
  860.     }
  861.     else
  862.     {
  863.         hr = CoGetClassObject(CLSID_JavaExecute,
  864.                               CLSCTX_INPROC_SERVER |
  865.                               CLSCTX_INPROC_HANDLER |
  866.                               CLSCTX_LOCAL_SERVER,
  867.                               NULL,
  868.                               IID_IClassFactory,
  869.                               (LPVOID*)(&pcf));
  870.         if (FAILED(hr))
  871.         {
  872.             FatalErrorHR(hr, IDS_JAVAVM);
  873.         }
  874.         else
  875.         {
  876.             // Getting the class factory should have loaded msjava.  Link its
  877.             // size-bounded sprintf functions.  If they're not there for some
  878.             // bizarre reason, we'll fall back on user's wsprintf.
  879.  
  880.             HMODULE hmodMSJAVA = GetModuleHandle("MSJAVA.DLL");
  881.             if (hmodMSJAVA)
  882.             {
  883.                 snprintfProc  *pfnsnprintf  = (snprintfProc *)GetProcAddress(hmodMSJAVA, "jio_snprintf");
  884.                 vsnprintfProc *pfnvsnprintf = (vsnprintfProc*)GetProcAddress(hmodMSJAVA, "jio_vsnprintf");
  885.  
  886.                 if (pfnsnprintf)  g_pfnsnprintf  = pfnsnprintf;
  887.                 if (pfnvsnprintf) g_pfnvsnprintf = pfnvsnprintf;
  888.             }
  889.  
  890.             hr = pcf->CreateInstance(NULL, IID_IJavaExecute, (LPVOID *)(&m_pJE));
  891.             if (FAILED(hr))
  892.             {
  893.                 m_pJE = NULL;
  894.                 FatalErrorHR(hr, IDS_CLASSLOADER);
  895.             }
  896.  
  897.             pcf->Release();
  898.         }
  899.  
  900.         if (NULL == m_pJE)
  901.             CoUninitialize();
  902.     }
  903.  
  904.     return (m_pJE != NULL);
  905. }
  906.  
  907. //------------------------------------------------------------------------------
  908. // CJView::MB2WC:
  909. //
  910. //   Converts the multibyte string to a UNICODE string, allocating space
  911. // for the destination string.
  912. //
  913. // Returns: Pointer to newly allocated and converted string, NULL if it fails
  914. //------------------------------------------------------------------------------
  915. LPWSTR CJView::m_MB2WC
  916. (
  917.     LPCSTR szAnsi,
  918.     int    cchAnsi
  919. )
  920. {
  921.    // First, determine size of converted string
  922.    //--------------------------------------------------------------------------
  923.    LPWSTR pwsz    = NULL;
  924.    int    cchWide = MultiByteToWideChar(0, 0, szAnsi, cchAnsi, NULL, 0) + 1;
  925.  
  926.    if (cchWide > 0)
  927.    {
  928.        // Got size so allocate the space and convert the string
  929.        //----------------------------------------------------------------------
  930.        if (pwsz = new WCHAR[cchWide])
  931.           MultiByteToWideChar(0, 0, szAnsi, cchAnsi, pwsz, cchWide);
  932.     }
  933.  
  934.    return pwsz;
  935. }
  936.  
  937. //------------------------------------------------------------------------------
  938. // CJView::m_WC2MB:
  939. //
  940. //   Converts the given UNICODE string to a multibyte string, allocating space
  941. // for the destination string.
  942. //
  943. // Returns: Pointer to newly allocated and converted string, NULL if it fails
  944. //------------------------------------------------------------------------------
  945. LPSTR CJView::m_WC2MB
  946. (
  947.    LPCWSTR pwsz,
  948.    int     cchWide
  949. )
  950. {
  951.    // First, determine size of converted string
  952.    //--------------------------------------------------------------------------
  953.    LPSTR psz     = NULL;
  954.    int   cchAnsi = WideCharToMultiByte(0, 0, pwsz, cchWide, NULL, 0, NULL, NULL);
  955.  
  956.    if (cchAnsi > 0)
  957.    {
  958.        // Got size so allocate the space and convert the string
  959.        //----------------------------------------------------------------------
  960.       if (psz = new CHAR[cchAnsi])
  961.           WideCharToMultiByte(0, 0, pwsz, cchWide, psz, cchAnsi, NULL, NULL);
  962.     }
  963.  
  964.     return psz;
  965. }
  966.  
  967.  
  968. //------------------------------------------------------------------------------
  969. // CJView::m_newSZ:
  970. //
  971. // Allocates the given string, generating OUT OF MEMORY if it fails
  972. //
  973. // Returns: LPSTR to allocated buffer if successful, NULL if not
  974. //------------------------------------------------------------------------------
  975. LPSTR CJView::m_newSZ
  976. (
  977.     int cBytes
  978. )
  979. {
  980.     LPSTR psz = new CHAR[cBytes + 1]; // +1 for \0
  981.  
  982.     if (!psz)
  983.         FatalError(IDS_OUTOFMEMORY);
  984.  
  985.     return psz;
  986. }
  987.  
  988.  
  989.  
  990. BOOL CJView::m_SetNamespace
  991. (
  992.     LPSTR pszNamespace
  993. )
  994. {
  995.     m_pszNamespace = m_MB2WC((LPCSTR) pszNamespace);
  996.  
  997.     if (m_pszNamespace == NULL)
  998.         return FALSE;
  999.     else
  1000.         return TRUE;
  1001. }
  1002.  
  1003.  
  1004. //------------------------------------------------------------------------------
  1005. // CJView::m_AppendPathString
  1006. //
  1007. // Appends the given path the the other given path, allocating and freeing
  1008. // as neccessary
  1009. //
  1010. // Returns: TRUE if successful, FALSE if not
  1011. //------------------------------------------------------------------------------
  1012. BOOL CJView::m_AppendPathString
  1013. (
  1014.     LPSTR *ppszPath,
  1015.     LPSTR  pszAppend
  1016. )
  1017. {
  1018.     LPSTR psz    = NULL;
  1019.     BOOL  fSemi2 = *CharPrev(pszAppend, pszAppend + lstrlen(pszAppend)) != ';';
  1020.  
  1021.     if (*ppszPath)
  1022.     {
  1023.         // Been here before, so we append the given string to the given path
  1024.         //----------------------------------------------------------------------
  1025.         if (!(psz = m_newSZ(lstrlen(*ppszPath))))
  1026.             return FALSE;
  1027.  
  1028.         lstrcpy(psz, *ppszPath);
  1029.         deleteSZ(*ppszPath);
  1030.  
  1031.         BOOL fSemi1 = *CharPrev(psz, psz + lstrlen(psz)) != ';';
  1032.  
  1033.         if (!(*ppszPath = m_newSZ(lstrlen(psz) + lstrlen(pszAppend) + fSemi1 + fSemi2)))
  1034.         {
  1035.             deleteSZ(psz);
  1036.             return FALSE;
  1037.         }
  1038.  
  1039.         lstrcpy(*ppszPath, psz);
  1040.  
  1041.         // Add semi-colon between paths if original path did not have one
  1042.         //----------------------------------------------------------------------
  1043.         if (fSemi1)
  1044.             lstrcat(*ppszPath, ";");
  1045.  
  1046.         lstrcat(*ppszPath, pszAppend);
  1047.         deleteSZ(psz);
  1048.     }
  1049.     else
  1050.     {
  1051.         // First time here, so copy Append string into Path
  1052.         //----------------------------------------------------------------------
  1053.         if (!(*ppszPath = m_newSZ(lstrlen(pszAppend) + fSemi2)))
  1054.             return FALSE;
  1055.  
  1056.         lstrcpy(*ppszPath , pszAppend);
  1057.     }
  1058.  
  1059.     // Append final semi-colon if string being append does not have one
  1060.     //--------------------------------------------------------------------------
  1061.     if (fSemi2)
  1062.         lstrcat(*ppszPath, ";");
  1063.  
  1064.     return TRUE;
  1065. }
  1066.  
  1067. //------------------------------------------------------------------------------
  1068. // CJView::m_DisplayUsage:
  1069. //
  1070. //  Displays the usage text for JView.exe
  1071. //
  1072. // Returns: Nothing
  1073. //------------------------------------------------------------------------------
  1074.  
  1075. #ifdef NO_CONSOLE
  1076.  
  1077. VOID CJView::m_DisplayUsage()
  1078. {
  1079.     CHAR  *pszBuffer;
  1080.     CHAR  *pchDest;
  1081.     CHAR  *pchSrc;
  1082.     CHAR  *pchSrc2;
  1083.     DWORD  dwCurBufferSize;
  1084.     DWORD  dwMaxBufferSize;
  1085.     CHAR   szTmp[BUFSIZE];
  1086.     INT    i = 0;
  1087.     DWORD  nChars;
  1088.     DWORD  nChars2;
  1089.  
  1090.     dwCurBufferSize = 0;
  1091.     dwMaxBufferSize = MAX_BUFFER;
  1092.     pszBuffer       = new(CHAR[dwMaxBufferSize]);
  1093.  
  1094.     if (!pszBuffer)
  1095.         return;
  1096.  
  1097.     // Pick up the copyright banner text.
  1098.  
  1099.     LoadStringX(NULL, IDS_BANNER1, szTmp, sizeof(szTmp));
  1100.  
  1101.     JVIEWsnprintf(pszBuffer, dwMaxBufferSize, szTmp,
  1102.              HIBYTE(HIWORD(VER_PRODUCTVERSION_DW)),
  1103.              LOBYTE(HIWORD(VER_PRODUCTVERSION_DW)),
  1104.              LOWORD(VER_PRODUCTVERSION_DW));
  1105.  
  1106.     dwCurBufferSize = lstrlen(pszBuffer);
  1107.     pchDest = pszBuffer + dwCurBufferSize;
  1108.  
  1109.     LoadStringX(NULL, IDS_BANNER2, szTmp, sizeof(szTmp));
  1110.     JVIEWsnprintf(pchDest, dwMaxBufferSize - dwCurBufferSize, szTmp, VER_LAST_COPYRIGHT_YEAR);
  1111.  
  1112.     dwCurBufferSize = lstrlen(pszBuffer);
  1113.  
  1114.     // Get the actual help text.
  1115.  
  1116.     pchSrc2 = NULL;
  1117.     nChars2 = 0;
  1118.  
  1119.     while (TRUE)
  1120.     {
  1121.         nChars = LoadStringX(NULL, IDS_USAGE1 + (i++), szTmp, sizeof(szTmp));
  1122.  
  1123.         if (*szTmp == '~')
  1124.             break;
  1125.  
  1126.         pchSrc = szTmp;
  1127.  
  1128.         if (*szTmp == '@')
  1129.         {
  1130. #ifdef PROFILER_HOOK
  1131.             IJVIEWProfiler *pProfiler = LoadProfilerSilently();
  1132.             if (!pProfiler)
  1133.                 continue;
  1134.  
  1135.             switch (szTmp[1])
  1136.             {
  1137.             case '1':
  1138.                 if (!m_fProfilerSupportsParameters)
  1139.                     continue;
  1140.                 break;
  1141.  
  1142.             case '2':
  1143.                 if (m_fProfilerSupportsParameters)
  1144.                     continue;
  1145.                 break;
  1146.  
  1147.             case '3':
  1148.                 pchSrc2 = pProfiler->GetUsageString();
  1149.                 if (!pchSrc2)
  1150.                     continue;
  1151.  
  1152.                 nChars2 = lstrlen(pchSrc2);
  1153.                 break;
  1154.  
  1155.             default:
  1156.                 continue;
  1157.             }
  1158.  
  1159.             nChars -= 2;
  1160.             pchSrc += 2;
  1161. #else
  1162.             continue;
  1163. #endif
  1164.         }
  1165.  
  1166.         if ( dwCurBufferSize + nChars + nChars2 > dwMaxBufferSize )
  1167.         {
  1168.             DWORD dwNewMax     = dwMaxBufferSize + MAX_BUFFER + nChars2;
  1169.             CHAR *pszTmpBuffer = new( CHAR[dwNewMax] );
  1170.  
  1171.             if (!pszTmpBuffer)
  1172.                 break;
  1173.  
  1174.             CopyMemory(pszTmpBuffer,pszBuffer,dwCurBufferSize);
  1175.             delete(pszBuffer);
  1176.  
  1177.             pszBuffer = pszTmpBuffer;
  1178.             dwMaxBufferSize = dwNewMax;
  1179.         }
  1180.  
  1181.         pchDest = pszBuffer + dwCurBufferSize;
  1182.  
  1183.         CopyMemory(pchDest, pchSrc, nChars);
  1184.  
  1185.         if (pchSrc2)
  1186.         {
  1187.             pchDest += nChars;
  1188.             
  1189.             CopyMemory(pchDest, pchSrc2, nChars2);
  1190.  
  1191.             CoTaskMemFree(pchSrc2);
  1192.             pchSrc2 = NULL;
  1193.             nChars2 = 0;
  1194.         }
  1195.  
  1196.         dwCurBufferSize += nChars + nChars2;
  1197.     }
  1198.  
  1199.     // Load up the caption title.  Reuse the printf format buffer.
  1200.     LoadStringX(NULL,IDS_WJVIEW_TITLE_HELP,szTmp,sizeof(szTmp));
  1201.  
  1202.     MessageBox(NULL,pszBuffer,"WJView Help",MB_OK);
  1203. }
  1204.  
  1205. #else
  1206.  
  1207. VOID CJView::m_DisplayUsage ()
  1208. {
  1209.     // NOTE: All usage lines must be sequential String
  1210.     //       IDS starting with IDS_USAGE1
  1211.     CHAR sz[BUFSIZE];
  1212.     INT  i = 0;
  1213.     DWORD nChars;
  1214.  
  1215.     m_DisplayBanner();
  1216.  
  1217.     while (TRUE)
  1218.     {
  1219.         nChars = LoadStringX(NULL, IDS_USAGE1 + (i++), sz, sizeof(sz));
  1220.  
  1221.         if (*sz == '~')
  1222.             break;
  1223.  
  1224.         CHAR *pchSrc = sz;
  1225.  
  1226.         if (*sz == '@')
  1227.         {
  1228. #ifdef PROFILER_HOOK
  1229.             IJVIEWProfiler *pProfiler = LoadProfilerSilently();
  1230.             if (!pProfiler)
  1231.                 continue;
  1232.  
  1233.             switch (sz[1])
  1234.             {
  1235.             case '1':
  1236.                 if (!m_fProfilerSupportsParameters)
  1237.                     continue;
  1238.                 break;
  1239.  
  1240.             case '2':
  1241.                 if (m_fProfilerSupportsParameters)
  1242.                     continue;
  1243.                 break;
  1244.  
  1245.             case '3':
  1246.                 PSTR pszProfilerUsage;
  1247.                 pszProfilerUsage = pProfiler->GetUsageString();
  1248.                 if (pszProfilerUsage)
  1249.                 {
  1250.                     WriteConsoleBasic(STD_OUTPUT_HANDLE, sz+2, nChars-2);
  1251.  
  1252.                     WriteConsoleBasic(STD_OUTPUT_HANDLE, pszProfilerUsage, -1);
  1253.  
  1254.                     LocalFree(pszProfilerUsage);
  1255.                 }
  1256.                 continue;
  1257.  
  1258.             default:
  1259.                 continue;
  1260.             }
  1261.  
  1262.             nChars -= 2;
  1263.             pchSrc = sz+2;
  1264. #else
  1265.             continue;
  1266. #endif
  1267.         }
  1268.  
  1269.         WriteConsoleBasic(STD_OUTPUT_HANDLE, pchSrc, nChars);
  1270.     }
  1271. }
  1272.  
  1273. #endif
  1274.  
  1275. //------------------------------------------------------------------------------
  1276. // CJView::m_ParseSwitches:
  1277. //
  1278. //  Parses off the switches portion of the command line
  1279. //
  1280. // Returns: TRUE if successful, FALSE if not
  1281. //------------------------------------------------------------------------------
  1282. BOOL CJView::m_ParseSwitches
  1283. (
  1284.     int *piArg
  1285. )
  1286. {
  1287.     BOOL   fSuccess = TRUE;
  1288.  
  1289. #ifndef APPLETVIEWER
  1290.  
  1291.     BOOL   fReplace = m_pszClassPath != NULL;
  1292.     LPSTR *ppsz;
  1293.     LPSTR  psz;
  1294.  
  1295.     *piArg = 1;
  1296.  
  1297.     // We support both '-' and '/' switch designators
  1298.     //--------------------------------------------------------------------------
  1299.     while ((*piArg < m_ac) && ((m_av[*piArg][0] == '-') || (m_av[*piArg][0] == '/')))
  1300.     {
  1301.         psz = CharNext(m_av[*piArg]);
  1302.  
  1303.         // Check for the -D switch prior to CharLowering the switch string.
  1304.  
  1305.         if ( (*psz == 'D' || *psz == 'd') && (*(psz+1)==':') )
  1306.         {
  1307.             char *pszPropStr = psz+2;
  1308.  
  1309.             if ( *pszPropStr == '\0' )
  1310.             {
  1311.                 FatalError(IDS_INVALIDSWITCH, psz);
  1312.                 fSuccess = FALSE;
  1313.                 break;
  1314.             }
  1315.  
  1316.             // If we don't already have a properties object, create one.
  1317.             if ( !m_pProperties )
  1318.             {
  1319.                 m_pProperties = new(CEnumJAVAPROPERTY);
  1320.  
  1321.                 if (!m_pProperties)
  1322.                 {
  1323.                     FatalError(IDS_OUTOFMEMORY);
  1324.                     fSuccess = FALSE;
  1325.                     break;
  1326.                 }
  1327.             }
  1328.  
  1329.             // Add the property to the property enumerator.
  1330.             m_pProperties->Add(psz+2);
  1331.         }
  1332.         else
  1333.         {
  1334.             // Check for usage switch first.  This is only valid as first switch
  1335.             //----------------------------------------------------------------------
  1336.             if (*piArg == 1 && lstrcmp(psz, "?") == 0)
  1337.             {
  1338.                 m_DisplayUsage();
  1339.                 fSuccess = FALSE;
  1340.                 break;
  1341.             }
  1342.  
  1343. #ifdef PROFILER_HOOK
  1344.             CHAR buf[5];
  1345.             *(DWORD*)buf = *(DWORD*)psz;
  1346.             buf[4] = '\0';
  1347.             if (lstrcmpi(buf, "prof") == 0 && (psz[4] == ':' || psz[4] == '\0'))
  1348.             {
  1349.                 *(DWORD*)psz = *(DWORD*)"prof";
  1350.             }
  1351.             else
  1352. #endif
  1353.             {
  1354.                 // All other switches are case insensitive, so just knock 'em down to
  1355.                 // lowercase here.
  1356.  
  1357.                 CharLower(psz);
  1358.             }
  1359.  
  1360.             // Check for "run in sun.applet.AppletViewer switch" , -a
  1361.             if (lstrcmp(psz, "a") == 0)
  1362.                 m_fApplet = TRUE;
  1363.             // Check for "pause after error switch" , -p
  1364.             else if (lstrcmp(psz, "p") == 0)
  1365.                 g_fPause = TRUE;
  1366.             // Check for "verify all" switch, -v
  1367.             else if (lstrcmp(psz, "v") == 0)
  1368.                 m_fVerify = TRUE;
  1369.             // Silently ignore the old "quiet" switch for compatibility with
  1370.             // existing scripts.
  1371.             else if (lstrcmp(psz, "q") == 0)
  1372.                 ;
  1373.             // check for "verbose stack traces" switch
  1374.             else if( lstrcmp( psz, "vst" ) == 0 )
  1375.                 m_fVerboseStackTraces = TRUE;
  1376. #ifdef PROFILER_HOOK
  1377.             else if (   *(DWORD*)psz == *(DWORD*)"prof"
  1378.                      && (psz[4] == ':' || psz[4] == '\0'))
  1379.             {
  1380.                 if (!ParseProfilingParams(psz+4))
  1381.                 {
  1382.                     // ParseProfilingParams has already displayed an error message.
  1383.                     fSuccess = FALSE;
  1384.                     break;
  1385.                 }
  1386.  
  1387.                 m_fEnableProfiling = TRUE;
  1388.             }
  1389. #endif
  1390. #ifndef NO_CONSOLE
  1391.             // Internal switches to control process affinity.
  1392.             else if ((lstrcmp(psz, "x:pa1") == 0) ||
  1393.                      (lstrcmp(psz, "x:pa2") == 0) ||
  1394.                      (lstrcmp(psz, "x:pa3") == 0) ||
  1395.                      (lstrcmp(psz, "x:pa4") == 0))
  1396.             {
  1397.                 typedef BOOL (WINAPI *PFNSETPROCESSAFFINITYMASK)(HANDLE, DWORD);
  1398.                 HMODULE hmodKernel = GetModuleHandle("KERNEL32");
  1399.                 PFNSETPROCESSAFFINITYMASK pfnSetProcessAffinityMask =
  1400.                     (PFNSETPROCESSAFFINITYMASK) GetProcAddress(hmodKernel,
  1401.                     "SetProcessAffinityMask");
  1402.  
  1403.                 if (pfnSetProcessAffinityMask != NULL)
  1404.                 {
  1405.                     pfnSetProcessAffinityMask(GetCurrentProcess(),
  1406.                         (1 << (psz[4] - '0')) - 1);
  1407.                 }
  1408.             }
  1409. #endif
  1410.             else
  1411.             {
  1412.                 // Check for classpath switches -cp, -cp:p, or -cp:a
  1413.                 //------------------------------------------------------------------
  1414.                 BOOL fAppend  = FALSE;
  1415.                 BOOL fPrepend = FALSE;
  1416.  
  1417.                 if (           !lstrcmp(psz, "cp")    ||
  1418.                    (fPrepend = !lstrcmp(psz, "cp:p")) ||
  1419.                    (fAppend  = !lstrcmp(psz, "cp:a")))
  1420.                 {
  1421.                     // We have classpath switch, so check for path.  If not given,
  1422.                     // i.e, we're out of arguments, it's a bogus command line
  1423.                     //--------------------------------------------------------------
  1424.                     if (++(*piArg) == m_ac ||
  1425.                        (m_av[*piArg][0] == '-' || m_av[*piArg][0] == '/'))
  1426.                     {
  1427.                         // We're about to exit, so we don't have to worry about
  1428.                         // losing information in the ANSI to OEM conversion.
  1429.                         CharToOemX((m_av[*piArg - 1], m_av[*piArg - 1]));
  1430.  
  1431.                         FatalError(IDS_NOPATHGIVEN, m_av[*piArg - 1]);
  1432.                         fSuccess = FALSE;
  1433.                         break;
  1434.                     }
  1435.  
  1436.                     // If we are given a class path on the command line and we also
  1437.                     // have a classpath from the environment variable CLASSPATH,
  1438.                     // the one given on the command line instructs us to ignore the
  1439.                     // environment variable, and we instead append/prepend other
  1440.                     // paths to this one instead
  1441.                     //--------------------------------------------------------------
  1442.                     if (fReplace && !(fPrepend || fAppend))
  1443.                     {
  1444.                         deleteSZ(m_pszClassPath);
  1445.                         fReplace = FALSE;
  1446.                     }
  1447.  
  1448.                     ppsz = fPrepend ? &m_pszPrepend : (fAppend ? &m_pszAppend :
  1449.                                                                  &m_pszClassPath);
  1450.                     m_AppendPathString(ppsz, m_av[*piArg]);
  1451.                 }
  1452.                 else if (!lstrcmp(psz, "n"))
  1453.                 {
  1454.                     // We have classpath switch, so check for path.  If not given,
  1455.                     // i.e, we're out of arguments, it's a bogus command line
  1456.                     //--------------------------------------------------------------
  1457.                     if (++(*piArg) == m_ac ||
  1458.                        (m_av[*piArg][0] == '-' || m_av[*piArg][0] == '/'))
  1459.                     {
  1460.                         // We're about to exit, so we don't have to worry about
  1461.                         // losing information in the ANSI to OEM conversion.
  1462.                         CharToOemX((m_av[*piArg - 1], m_av[*piArg - 1]));
  1463.  
  1464.                         FatalError(IDS_NONAMESPACEGIVEN, m_av[*piArg - 1]);
  1465.                         fSuccess = FALSE;
  1466.                         break;
  1467.                     }
  1468.  
  1469.                     (void) m_SetNamespace(m_av[*piArg]);
  1470.                 }
  1471.                 else
  1472.                 {
  1473.                     // We're about to exit, so we don't have to worry about
  1474.                     // losing information in the ANSI to OEM conversion.
  1475.                     CharToOemX((m_av[*piArg], m_av[*piArg]));
  1476.  
  1477.                     // Bogus switch!
  1478.                     FatalError(IDS_INVALIDSWITCH, m_av[*piArg]);
  1479.                     fSuccess = FALSE;
  1480.                     break;
  1481.                 }
  1482.             }
  1483.         }
  1484.  
  1485.         (*piArg)++;
  1486.     }
  1487.  
  1488. #endif
  1489.  
  1490.     return fSuccess;
  1491. }
  1492.  
  1493. //------------------------------------------------------------------------------
  1494. // CJView::m_ParseParameters
  1495. //
  1496. // Parses off the remaining command line arguments following the class simply
  1497. // copying them into a list of OLESTRS
  1498. //
  1499. // Returns: TRUE if successful, FALSE if not
  1500. //------------------------------------------------------------------------------
  1501. BOOL CJView::m_ParseParameters
  1502. (
  1503.     int iNext
  1504. )
  1505. {
  1506.     // If applet or stand-alone, we need a values array
  1507.     //--------------------------------------------------------------------------
  1508.     m_iArgs = m_ac - iNext;
  1509.  
  1510.     m_ppszArgs = new LPOLESTR[m_iArgs + 1];
  1511.     if (!m_ppszArgs)
  1512.     {
  1513.         FatalError(IDS_OUTOFMEMORY);
  1514.         return FALSE;
  1515.     }
  1516.  
  1517.     (m_ppszArgs)[0] = NULL; // Initially empty!
  1518.  
  1519.     // Now, run through the list of arguments and process
  1520.     //--------------------------------------------------------------------------
  1521.     int i;
  1522.  
  1523.     for (i = 0; i < m_iArgs; i++)
  1524.     {
  1525.         if (!((m_ppszArgs)[i] = m_MB2WC(m_av[iNext++])))
  1526.             break;
  1527.     }
  1528.  
  1529.     // If succesful, mark end of array
  1530.     //--------------------------------------------------------------------------
  1531.     if (i == m_iArgs)
  1532.     {
  1533.         (m_ppszArgs)[i] = NULL;
  1534.     }
  1535.     else
  1536.     {
  1537.         // Clean up if we fail
  1538.         //----------------------------------------------------------------------
  1539.         int n;
  1540.  
  1541.         for (n = 0; n < i; n++)
  1542.             deleteSZ(m_ppszArgs[n]);
  1543.         deleteSZ(m_ppszArgs);
  1544.     }
  1545.  
  1546.     return (i == m_iArgs);
  1547. }
  1548.  
  1549. //------------------------------------------------------------------------------
  1550. // CJView::ParseCommandLine:
  1551. //
  1552. //  Parses the command line, which must be in the format:
  1553. //
  1554. //  JView [switches] ClassName [Parameters]
  1555. //
  1556. //  switches:   None          :  Invoke main()
  1557. //              -a            :  Run as Applet
  1558. //              -cp   <path>  :  Set CLASSPATH to <path.
  1559. //              -cp:p <path>  :  Prepend <path> to CLASSPATH
  1560. //              -cp:a <path>  :  Append  <path> to CLASSPATH
  1561. //
  1562. //  Classname:  Class file to run.  Valid previously compiled .JAVA file(s)
  1563. //
  1564. //  Parameters: Name=Value
  1565. //
  1566. //              if value contains spaces, value must be contained in double
  1567. //              quotes
  1568. //
  1569. //              Name="Value contains spaces"
  1570. //
  1571. // Returns: TRUE if successful, FALSE if not
  1572. //------------------------------------------------------------------------------
  1573. BOOL CJView::ParseCommandLine ()
  1574. {
  1575. #ifdef APPLETVIEWER
  1576.  
  1577.     return m_ac > 1 ? m_ParseParameters(1) : TRUE;
  1578.  
  1579. #else
  1580.  
  1581.     // Must have at least one command line arguement of class name
  1582.     // Argument 0 is JVIEW itself
  1583.     //--------------------------------------------------------------------------
  1584.     if (m_ac == 1)
  1585.     {
  1586.         m_DisplayUsage();
  1587.         return FALSE;
  1588.     }
  1589.  
  1590.     // Get current CLASSPATH from VM.  We start with this, and append, prepend,
  1591.     // or replace it with what we find on the command line
  1592.     //--------------------------------------------------------------------------
  1593.     LPOLESTR psz = NULL;
  1594.  
  1595.     if (m_pszClassPath = new CHAR[1])
  1596.         *m_pszClassPath = 0;
  1597.  
  1598.     // First thing we check for are switches, processing all arguments that
  1599.     // begin with "-".
  1600.     // NOTE: All switches must come before class name and parameters
  1601.     //--------------------------------------------------------------------------
  1602.     INT i;
  1603.  
  1604.     if (!m_ParseSwitches(&i))
  1605.         return FALSE;
  1606.  
  1607.     // Next on the command line should be the class file to execute.  If no more
  1608.     // arguments, it's a bogus command line
  1609.     //--------------------------------------------------------------------------
  1610.     BOOL fSuccess = TRUE;
  1611.  
  1612.     if (i == m_ac)
  1613.     {
  1614.         FatalError(IDS_NOCLASSGIVEN);
  1615.         fSuccess = FALSE;
  1616.     }
  1617.     else
  1618.     {
  1619.         INT len;
  1620.         // OK, we have another argument, so whatever it is we simply treat it as
  1621.         // the class file name and let the VM deal with verifying it.
  1622.         //----------------------------------------------------------------------
  1623.         if (m_pszClassName = m_newSZ(len = lstrlen(m_fApplet ? APPLETVIEWER_CLASS : m_av[i])))
  1624.         {
  1625.             lstrcpy(m_pszClassName, m_fApplet ? APPLETVIEWER_CLASS : m_av[i++]);
  1626.  
  1627.             // Keep track of the class name in a global.  Note that we alias the
  1628.             // real m_pszClassName here.  Need to be careful about lifetimes.
  1629.             g_pszMainClass = m_pszClassName;
  1630.  
  1631.             OSVERSIONINFO osvi;
  1632.             osvi.dwOSVersionInfoSize = sizeof(osvi);
  1633.  
  1634.             if (len && GetVersionEx(&osvi) && (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT))
  1635.             {
  1636.                 INT j = i;
  1637.  
  1638.                 // compute of length of title
  1639.  
  1640.                 len += lstrlen("JVIEW ") + 1; // +1 for \0
  1641.                 while (j < m_ac)
  1642.                 {
  1643.                     len += lstrlen(m_av[j++]) + 1; // +1 for ' '
  1644.                 }
  1645.  
  1646.  
  1647.                 LPSTR title = new CHAR[len]; // +1 for \0
  1648.                 if (title)
  1649.                 {
  1650.                     lstrcpy(title, "JVIEW ");
  1651.                     lstrcat(title,g_pszMainClass);
  1652.                     j = i;
  1653.  
  1654.                     while (j < m_ac)
  1655.                     {
  1656.                         lstrcat(title, " ");
  1657.                         lstrcat(title, m_av[j++]);
  1658.                     }
  1659.  
  1660.                     SetConsoleTitle(title);
  1661.                     delete title;
  1662.                 }
  1663.             }
  1664.  
  1665.  
  1666.             // Finally, if we have any more arguments, they are all treated as
  1667.             // parameters to be used by the class
  1668.             //------------------------------------------------------------------
  1669.             if (i < m_ac)
  1670.                 fSuccess = m_ParseParameters(i);
  1671.         }
  1672.     }
  1673.  
  1674.     if (fSuccess)
  1675.     {
  1676.         // Build final path string
  1677.         //----------------------------------------------------------------------
  1678.         if (m_pszPrepend)
  1679.         {
  1680.             if (m_pszClassPath)
  1681.                 m_AppendPathString(&m_pszPrepend, m_pszClassPath);
  1682.             deleteSZ(m_pszClassPath);
  1683.             m_pszClassPath = m_pszPrepend;
  1684.             m_pszPrepend   = NULL;
  1685.         }
  1686.  
  1687.         if (m_pszAppend)
  1688.         {
  1689.             if (m_pszClassPath)
  1690.             {
  1691.                 m_AppendPathString(&m_pszClassPath, m_pszAppend);
  1692.                 deleteSZ(m_pszAppend);
  1693.             }
  1694.             else
  1695.             {
  1696.                 m_pszClassPath = m_pszAppend;
  1697.                 m_pszAppend    = NULL;
  1698.             }
  1699.         }
  1700.     }
  1701.  
  1702.     return fSuccess;
  1703.  
  1704. #endif
  1705. }
  1706.  
  1707.  
  1708. #ifndef NO_CONSOLE
  1709.  
  1710. //------------------------------------------------------------------------------
  1711. // CJView::m_DisplayBanner:
  1712. //
  1713. //  Displays the banner for JView.exe
  1714. //
  1715. // Returns: Nothing
  1716. //------------------------------------------------------------------------------
  1717. VOID CJView::m_DisplayBanner ()
  1718. {
  1719.     CHAR sz[BUFSIZE];
  1720.  
  1721.     LoadStringX(NULL, IDS_BANNER1, sz, sizeof(sz));
  1722.     WriteConsolePrintf(STD_OUTPUT_HANDLE, sz,
  1723.         HIBYTE(HIWORD(VER_PRODUCTVERSION_DW)),
  1724.         LOBYTE(HIWORD(VER_PRODUCTVERSION_DW)),
  1725.         LOWORD(VER_PRODUCTVERSION_DW));
  1726.     LoadStringX(NULL, IDS_BANNER2, sz, sizeof(sz));
  1727.     WriteConsolePrintf(STD_OUTPUT_HANDLE, sz, VER_LAST_COPYRIGHT_YEAR);
  1728. }
  1729.  
  1730. #endif
  1731.  
  1732.  
  1733. //------------------------------------------------------------------------------
  1734. // CJView::Initialize:
  1735. //
  1736. //  Performs initialization for CJView
  1737. //
  1738. // Returns: TRUE if successful, FALSE if not
  1739. //------------------------------------------------------------------------------
  1740. BOOL CJView::Initialize ()
  1741. {
  1742.    return m_InitComAndJava();
  1743. }
  1744.  
  1745. //------------------------------------------------------------------------------
  1746. // RunMessageLoop:
  1747. //      Message pump for OLE
  1748. //
  1749. //------------------------------------------------------------------------------
  1750. UINT RunMessageLoop(void)
  1751. {
  1752.     MSG msg;
  1753.  
  1754.     // No accelerators to load.  Get and dispatch messages until a WM_QUIT
  1755.     // message is received.
  1756.     ZeroMemory(&msg, sizeof(msg));
  1757.  
  1758.     msg.wParam = S_OK;
  1759.  
  1760.     while (GetMessage(&msg, NULL, 0, 0))
  1761.     {
  1762.       //
  1763.       // Dispatch message to target window.
  1764.       //
  1765.       // To host activex controls, this is required.
  1766.       //
  1767.       TranslateMessage(&msg);
  1768.       DispatchMessage(&msg);
  1769.     }
  1770.  
  1771.     return(msg.wParam);
  1772. }
  1773.  
  1774. //------------------------------------------------------------------------------
  1775. // CJView::SetSystemProperties:
  1776. //
  1777. // Will inform the VM of any additional system properties that we want to
  1778. // set.
  1779.  
  1780. HRESULT CJView::SetSystemProperties()
  1781. {
  1782.     HRESULT        hr;
  1783.     IJavaExecute2 *pije2;
  1784.  
  1785. #ifndef APPLETVIEWER
  1786.     // If no properties defined or not running the applet viewer, bail.
  1787.     if ( !m_pProperties && !m_fApplet )
  1788.         return S_OK;
  1789. #endif
  1790.  
  1791.     // Query for the IJavaExecute2 interface off of the existing
  1792.     // IJavaExecute interface.
  1793.     if (m_pJE->QueryInterface(IID_IJavaExecute2, (LPVOID*)&pije2) == S_OK)
  1794.     {
  1795.         if (m_fApplet)
  1796.         {
  1797.             CEnumResourceJAVAPROPERTY *perjp =
  1798.                 new CEnumResourceJAVAPROPERTY(g_AppletViewerProperties,
  1799.                 ARRAY_ELEMENTS(g_AppletViewerProperties));
  1800.  
  1801.             hr = pije2->SetSystemProperties((IEnumJAVAPROPERTY *) perjp);
  1802.             perjp->Release();
  1803.         }
  1804.         else
  1805.         {
  1806.             hr = S_OK;
  1807.         }
  1808.  
  1809. #ifndef APPLETVIEWER
  1810.         if (hr == S_OK && m_pProperties)
  1811.         {
  1812.             // We found IJavaExecute2, set the system properties.
  1813.             hr = pije2->SetSystemProperties( (IEnumJAVAPROPERTY *)m_pProperties);
  1814.         }
  1815. #endif
  1816.  
  1817.         pije2->Release();
  1818.     }
  1819.     else
  1820.     {
  1821.         // If the QI failed, this current VM does not support IJavaExecute2
  1822.         hr = E_FAIL;
  1823.         FatalError(IDS_PROPSNOTSUPPORTED);
  1824.     }
  1825.  
  1826.     return hr;
  1827. }
  1828.  
  1829. //------------------------------------------------------------------------------
  1830. // CJView::ExecuteClass:
  1831. //
  1832. //  Executes the given class file
  1833. //
  1834. // Returns: result of IJavaExecute::Execute
  1835. //------------------------------------------------------------------------------
  1836.  
  1837. HRESULT CJView::ExecuteClass (LPERRORINFO *ppIErrorInfo)
  1838. {
  1839.     LPOLESTR        pszClassName;
  1840.     LPOLESTR        pszClassPath;
  1841.     JAVAEXECUTEINFO jei;
  1842.  
  1843.     pszClassName = m_MB2WC(m_pszClassName);
  1844.     pszClassPath = m_MB2WC(m_pszClassPath);
  1845.  
  1846.     jei.cbSize       = sizeof(jei);
  1847.     jei.dwFlags      = (JEIF_ACTIVEXDEBUG |
  1848.                         JEIF_DEBUGGEE_SHUTDOWN_ON_RELEASE |
  1849. #if !defined(NO_CONSOLE) && !defined(APPLETVIEWER)
  1850.                         JEIF_PRINTUNHANDLEDSTACKTRACE |
  1851. #endif
  1852.                         (m_fVerify ? JEIF_VERIFYCLASSES : 0) |
  1853.                         (m_fApplet ? JEIF_INSTALLSTANDARDSECURITY : 0) |
  1854.                         (m_fVerboseStackTraces ? JEIF_VERBOSESTACKTRACES : 0)
  1855.                        );
  1856. #ifdef APPLETVIEWER
  1857.     jei.pszClassName = APPLETVIEWER_CLASS;
  1858. #else
  1859.     jei.pszClassName = pszClassName;
  1860. #endif
  1861.  
  1862.     if ( m_fApplet )
  1863.         jei.dwFlags  = jei.dwFlags | JEIF_APPLETVIEWER;
  1864.  
  1865.     jei.rgszArgs     = (LPCOLESTR *)(m_ppszArgs);
  1866.     jei.cArgs        = m_iArgs;
  1867.     jei.pszClassPath = pszClassPath;
  1868.     jei.pszNamespace = m_pszNamespace;
  1869.  
  1870.     if (jei.pszNamespace != NULL)
  1871.         jei.dwFlags |= JEIF_NAMESPACE_SPECIFIED;
  1872.  
  1873.     HRESULT hr = m_pJE->Execute(&jei, ppIErrorInfo);
  1874.  
  1875.     deleteSZ(pszClassPath);
  1876.     deleteSZ(pszClassName);
  1877.     return hr;
  1878. }
  1879.  
  1880.  
  1881. //------------------------------------------------------------------------
  1882.  
  1883. #ifdef PROFILER_HOOK
  1884.  
  1885. class ProfilerFactory : public IClassFactory
  1886. {
  1887.     IJVIEWProfiler *m_pProfiler;
  1888.     ULONG m_refcount;
  1889.  
  1890. public:
  1891.  
  1892.     ProfilerFactory (IJVIEWProfiler *pProfiler)
  1893.     {
  1894.         (m_pProfiler = pProfiler)->AddRef();
  1895.         m_refcount = 1;
  1896.     }
  1897.     
  1898.     ~ProfilerFactory ()
  1899.     {
  1900.         m_pProfiler->Release();
  1901.     }
  1902.  
  1903.  
  1904.     // IUnknown methods
  1905.     
  1906.     STDMETHODIMP QueryInterface (REFIID riid, void **ppv)
  1907.     {
  1908.         if (   riid == IID_IClassFactory
  1909.             || riid == IID_IUnknown)
  1910.         {
  1911.             *ppv = (IClassFactory*)this;
  1912.         }
  1913.         else
  1914.         {
  1915.             *ppv = NULL;
  1916.             return E_NOINTERFACE;
  1917.         }
  1918.  
  1919.         AddRef();
  1920.         return S_OK;
  1921.     }
  1922.     
  1923.     STDMETHODIMP_(ULONG) AddRef ()
  1924.     {
  1925.         return InterlockedIncrement((LONG*)&m_refcount);
  1926.     }
  1927.     
  1928.     STDMETHODIMP_(ULONG) Release ()
  1929.     {
  1930.         ULONG refcount = (ULONG)InterlockedIncrement((LONG*)&m_refcount);
  1931.         if (!refcount)
  1932.             delete this;
  1933.         return refcount;
  1934.     }
  1935.  
  1936.  
  1937.     // IClassFactory methods
  1938.     
  1939.     STDMETHODIMP CreateInstance (LPUNKNOWN punkOuter, REFIID riid, void **ppv)
  1940.     {
  1941.         return !punkOuter ? m_pProfiler->QueryInterface(riid, ppv) : CLASS_E_NOAGGREGATION;
  1942.     }
  1943.  
  1944.     STDMETHODIMP LockServer (BOOL)
  1945.     {
  1946.         return E_NOTIMPL;
  1947.     }
  1948. };
  1949.  
  1950.  
  1951. HRESULT AppendEnvironmentVariable (PCSTR varname, PCSTR delim, PCSTR cat)
  1952. {
  1953.     CHAR buf[256];
  1954.     PSTR pbuf = &buf[0];
  1955.     unsigned bufsize = sizeof(buf);
  1956.     DWORD len;
  1957.     unsigned delimlen = strlen(delim);
  1958.     unsigned catlen = strlen(cat);
  1959.     unsigned extraneeded = delimlen+catlen+1;
  1960.  
  1961.     while (1)
  1962.     {
  1963.         len = GetEnvironmentVariable(varname, pbuf, bufsize);
  1964.         if (len < bufsize)
  1965.             break;
  1966.     mkbuf:
  1967.         bufsize = len+extraneeded;
  1968.         pbuf = new CHAR[bufsize];
  1969.         if (pbuf == NULL)
  1970.             return E_OUTOFMEMORY;
  1971.     }
  1972.  
  1973.     if (len+extraneeded > bufsize)
  1974.         goto mkbuf;
  1975.  
  1976.     if (len == 0)
  1977.         delimlen = 0;
  1978.         
  1979.     CopyMemory(pbuf+len, delim, delimlen);
  1980.     CopyMemory(pbuf+len+delimlen, cat, catlen+1);
  1981.  
  1982.     BOOL result = SetEnvironmentVariable(varname, pbuf);
  1983.  
  1984.     if (pbuf != &buf[0])
  1985.         delete pbuf;
  1986.  
  1987.     return result ? S_OK : E_FAIL;
  1988. }
  1989.  
  1990. #endif // PROFILER_HOOK
  1991.  
  1992.  
  1993. //------------------------------------------------------------------------------
  1994. // RunClassThread
  1995. //
  1996. //  Executes the given class file.  If not found, executes without .class
  1997. //  extension, if it has it.
  1998. //
  1999. // Returns: 0 if successful, 1 if not
  2000. //------------------------------------------------------------------------------
  2001.  
  2002. DWORD _stdcall RunClassThread
  2003. (
  2004.     PVOID pv
  2005. )
  2006. {
  2007.     CJView* pJV     = (CJView*)pv;
  2008.     int     iResult = 1;            // Assume failure.
  2009.  
  2010.     if (FAILED(CoInitialize(NULL)))
  2011.         return iResult;
  2012.  
  2013.     if (pJV->ParseCommandLine())
  2014.     {
  2015.         HRESULT hr = S_OK;
  2016.         LPERRORINFO     pIErrorInfo = NULL;
  2017.         char *classnameext = NULL;
  2018.  
  2019. #ifndef APPLETVIEWER
  2020.  
  2021.         // Check for prepended path
  2022.  
  2023.         int len = strlen(pJV->m_pszClassName);
  2024.  
  2025.         if (len > 2 && (pJV->m_pszClassName[1] == ':' || strchr(pJV->m_pszClassName,'\\') != NULL))
  2026.         {
  2027.             char *fullname = pJV->m_newSZ(MAX_PATH);
  2028.             char *endofpath;
  2029.  
  2030.             if (GetFullPathName(pJV->m_pszClassName, MAX_PATH+1, fullname, &endofpath))
  2031.             {
  2032.                 if ( endofpath )
  2033.                 {
  2034.                     // Convert to long filename, if needed
  2035.  
  2036.                     WIN32_FIND_DATA findinfo;
  2037.                     HANDLE hfind;
  2038.  
  2039.                     hfind = FindFirstFile(fullname, &findinfo);
  2040.  
  2041.                     if (hfind == INVALID_HANDLE_VALUE)
  2042.                     {
  2043.                         // Try appending a .class extension
  2044.  
  2045.                         strcat(endofpath, ".class");
  2046.  
  2047.                         hfind = FindFirstFile(fullname, &findinfo);
  2048.                     }
  2049.  
  2050.                     if (hfind != INVALID_HANDLE_VALUE)
  2051.                     {
  2052.                         // Split path from name
  2053.  
  2054.                         *(endofpath-1) = '\0';
  2055.  
  2056.                         // Create the real class name and update length
  2057.  
  2058.                         deleteSZ(pJV->m_pszClassName);
  2059.                         len = lstrlen(findinfo.cFileName);
  2060.                         pJV->m_pszClassName = pJV->m_newSZ(len);
  2061.                         lstrcpy(pJV->m_pszClassName, findinfo.cFileName);
  2062.  
  2063.                         // Prepend to specified path
  2064.  
  2065.                         if (*pJV->m_pszClassPath == '\0')
  2066.                         {
  2067.                             deleteSZ(pJV->m_pszClassPath);
  2068.                             pJV->m_pszClassPath = fullname;
  2069.                         }
  2070.                         else
  2071.                         {
  2072.                             pJV->m_AppendPathString(&fullname, pJV->m_pszClassPath);
  2073.                             deleteSZ(pJV->m_pszClassPath);
  2074.                             pJV->m_pszClassPath = fullname;
  2075.                         }
  2076.  
  2077.                         FindClose(hfind);
  2078.                     }
  2079.                 }
  2080.             }
  2081.  
  2082.             // else let the vm deal with whatever was specified.
  2083.         }
  2084.  
  2085.         // Check for .class extension.
  2086.  
  2087.         const char classext1[] = ".cla";
  2088.         const int classext1len = sizeof(classext1)-1;
  2089.         const char classext2[] = ".class";
  2090.         const int classext2len = sizeof(classext2)-1;
  2091.  
  2092.         if (len > classext1len)
  2093.         {
  2094.             char *ext = pJV->m_pszClassName+len-classext1len;
  2095.  
  2096.             if (lstrcmpi(ext, classext1) == 0)
  2097.             {
  2098.                 // Truncate at extension.
  2099.  
  2100.                 *ext = '\0';
  2101.                 classnameext = ext;
  2102.             }
  2103.             else
  2104.             {
  2105.                 // Try the full extension.
  2106.  
  2107.                 ext -= classext2len-classext1len;
  2108.  
  2109.                 if (lstrcmpi(ext, classext2) == 0)
  2110.                 {
  2111.                     *ext = '\0';
  2112.                     classnameext = ext;
  2113.                 }
  2114.             }
  2115.         }
  2116.  
  2117. #endif
  2118.  
  2119. #ifdef PROFILER_HOOK
  2120.         if (pJV->m_fEnableProfiling)
  2121.         {
  2122.             hr = AppendEnvironmentVariable("MSJAVA_EVENT_MONITORS", ";", CLSIDSTR_JVIEWEventMonitor);
  2123.  
  2124.             if (hr == S_OK)
  2125.             {
  2126.                 hr = SetEnvironmentVariable("MSJAVA_ENABLE_MONITORS", "1") ? S_OK : E_FAIL;
  2127.             }
  2128.  
  2129.             if (hr == S_OK)
  2130.             {
  2131.                 ProfilerFactory *pfact = new ProfilerFactory(pJV->m_pProfiler);
  2132.                 if (pfact)
  2133.                 {
  2134.                     IUnknown *punkfact;
  2135.                     if (pfact->QueryInterface(IID_IUnknown, (PVOID*)&punkfact) == S_OK)
  2136.                     {
  2137.                         DWORD dwRegister;
  2138.                     
  2139.                         hr = CoRegisterClassObject(
  2140.                                 CLSID_JVIEWEventMonitor,
  2141.                                 punkfact,
  2142.                                 CLSCTX_INPROC_SERVER,
  2143.                                 REGCLS_MULTIPLEUSE,
  2144.                                 &dwRegister);
  2145.  
  2146.                         punkfact->Release();
  2147.                     }
  2148.  
  2149.                     pfact->Release();
  2150.                 }
  2151.                 else
  2152.                 {
  2153.                     hr = E_OUTOFMEMORY;
  2154.                 }
  2155.             }
  2156.  
  2157.             if (hr != S_OK)
  2158.                 FatalError(IDS_COULDNOTREGPROF);
  2159.         }
  2160. #endif
  2161.  
  2162.         if (hr == S_OK)
  2163.         {
  2164.             // Set any user defined system properties.
  2165.             hr = pJV->SetSystemProperties();
  2166.         }
  2167.  
  2168.         if ( hr == S_OK )
  2169.         {
  2170.             hr = pJV->ExecuteClass(&pIErrorInfo);
  2171.  
  2172.             if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) && classnameext != NULL)
  2173.             {
  2174.                 // Try the 1 in a billion possibility that someone is trying
  2175.                 // to execute some class named 'class' in a package.  Of course,
  2176.                 // if someone has a class with the same name as the package, we
  2177.                 // hit it first above.
  2178.  
  2179.                 *classnameext = '.';
  2180.  
  2181.                 hr = pJV->ExecuteClass(&pIErrorInfo);
  2182.             }
  2183.  
  2184.             if (pIErrorInfo)
  2185.             {
  2186.                 // VM threw an exception while running the .class file.  We
  2187.                 // get the info via the returned IErrorInfo interface
  2188.                 BSTR bstrError = NULL;
  2189.  
  2190.                 if (SUCCEEDED(pIErrorInfo->GetDescription(&bstrError)))
  2191.                 {
  2192.                     LPSTR pszError = pJV->m_WC2MB(bstrError);
  2193.  
  2194.                     if (pszError)
  2195.                     {
  2196.                         CharToOemX((pszError, pszError));
  2197.                         FatalError (0, pszError);
  2198.                         deleteSZ(pszError);
  2199.                     }
  2200.                     else
  2201.                         FatalError (IDS_UNKNOWNERROR);
  2202.  
  2203.                     SysFreeString(bstrError);
  2204.                 }
  2205.                 else
  2206.                     FatalError(IDS_UNKNOWNERROR);
  2207.  
  2208.                 iResult = 1;
  2209.  
  2210.                 pIErrorInfo->Release();
  2211.             }
  2212.             else if (!SUCCEEDED(hr))
  2213.             {
  2214.                 // We're about to exit, so we don't have to worry about
  2215.                 // losing information in the ANSI to OEM conversion.
  2216.                 CharToOemX((pJV->m_pszClassName, pJV->m_pszClassName));
  2217.  
  2218.                 // Most likely .class file did not exist
  2219.                 FatalErrorHR (hr, IDS_EXECUTINGCLASS, pJV->m_pszClassName);
  2220.                 iResult = 1;
  2221.             }
  2222.             else
  2223.                 // Success.
  2224.                 iResult = 0;
  2225.         }
  2226.     }
  2227.  
  2228. #ifdef PROFILER_HOOK
  2229.     if (pJV->m_pProfiler)
  2230.     {
  2231.         pJV->m_pProfiler->Shutdown();
  2232.     }
  2233. #endif
  2234.  
  2235.     // Terminate message pump
  2236.     PostThreadMessage(pJV->m_dwMsgLoopThreadID, WM_QUIT, 0, 0);
  2237.  
  2238.     CoUninitialize();
  2239.  
  2240.     return (DWORD)iResult;
  2241. }
  2242.  
  2243. //------------------------------------------------------------------------------
  2244. // main - Entry point for JView
  2245. //
  2246. // Returns: 0 if successful, 1 if not
  2247. //------------------------------------------------------------------------------
  2248.  
  2249.  
  2250. #ifdef NO_CONSOLE
  2251. extern "C" int __argc;
  2252. extern "C" char ** __argv;
  2253. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  2254. {
  2255.     int argc = __argc;
  2256.     char **argv = __argv;
  2257. #else
  2258. int __cdecl main (int argc, char *argv[])
  2259. {
  2260. #endif
  2261.     int     iRet = 1;
  2262.     CJView* pJV;
  2263.  
  2264.     pJV = new CJView(argc, argv);
  2265.  
  2266.     if (!pJV)
  2267.     {
  2268.         FatalError(IDS_OUTOFMEMORY);
  2269.         goto exit;
  2270.     }
  2271.  
  2272.     if (pJV->Initialize())
  2273.     {
  2274.         // OK, we're ready, everything is done on the applet thread
  2275.         HANDLE hth;
  2276.         DWORD  dwThreadID;
  2277.  
  2278.         pJV->m_dwMsgLoopThreadID = GetCurrentThreadId();
  2279.         hth = CreateThread(NULL, 0, &RunClassThread, pJV, 0, &dwThreadID);
  2280.  
  2281.         if (hth)
  2282.         {
  2283.             RunMessageLoop();
  2284.  
  2285.             // If we returned from RunMessageLoop() as a result of
  2286.             // RunClassThread() posting the WM_QUIT message, then the thread
  2287.             // will be exiting shortly (if not already).  We wait for it to
  2288.             // terminate and grab its exit code.  1/2 second is plenty --
  2289.             // if the thread doesn't die by then, something is wrong (we
  2290.             // got a quit message from someone else, perhaps?) in which case
  2291.             // we return 1 for failure.
  2292.  
  2293.             if (WaitForSingleObject (hth, 500) == WAIT_OBJECT_0)
  2294.             {
  2295.                 DWORD   dwRetCode = 1;
  2296.  
  2297.                 // Thread's dead, baby... thread's dead...
  2298.                 GetExitCodeThread (hth, &dwRetCode);
  2299.                 iRet = dwRetCode;
  2300.             }
  2301.             CloseHandle(hth);
  2302.             hth = NULL;
  2303.         }
  2304.         else
  2305.         {
  2306.             FatalErrorHR(LAST_WIN32_ERROR_TO_HRESULT(),
  2307.                                 IDS_NOJAVATHREAD);
  2308.         }
  2309.     }
  2310.  
  2311.     delete pJV;
  2312.  
  2313. exit:
  2314.     ExitProcess(iRet);
  2315.     return iRet;
  2316. }
  2317.  
  2318. //
  2319. // Loads a resource and returns a pointer to the raw resource data.
  2320. // We add some additional language search order semantics on top
  2321. // of the standard FindResourceEx behavior:
  2322. //
  2323. // I've seen different behavior between NT and Win9x when the 
  2324. // specified language is LANG_SYSTEM_DEFAULT or LANG_USER_DEFAULT.
  2325. // We manually expand either of these language specifiers to 
  2326. // the current system values from either GetXDefaultLangID.
  2327. //
  2328. // If we don't find a resource with the specified language, we 
  2329. // explicitly fall back to US/English and reattempt the search.
  2330. //
  2331.  
  2332. LPVOID VMGetResource(
  2333.     HINSTANCE hModule,
  2334.     LPCTSTR   lpType,
  2335.     LPCTSTR   lpName,
  2336.     LANGID    wLanguage)
  2337. {
  2338.     HRSRC   hResource       = NULL;
  2339.     HGLOBAL hLoadedResource = NULL;
  2340.  
  2341.     if ( wLanguage == LANG_SYSTEM_DEFAULT )
  2342.         wLanguage = GetSystemDefaultLangID();
  2343.     else if ( wLanguage == LANG_USER_DEFAULT )
  2344.         wLanguage = GetUserDefaultLangID();
  2345.     
  2346.     hResource = FindResourceEx(hModule,lpType,lpName,wLanguage);
  2347.     
  2348.     if ( hResource )
  2349.         hLoadedResource = LoadResource(hModule,hResource);
  2350.     
  2351.     if ( !hLoadedResource )
  2352.     {
  2353.         wLanguage = MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US);
  2354.         
  2355.         hResource = FindResourceEx(hModule,lpType,lpName,wLanguage); 
  2356.     
  2357.         if ( hResource )
  2358.             hLoadedResource = LoadResource(hModule,hResource);
  2359.     }
  2360.     
  2361.     return (LPVOID)hLoadedResource;
  2362. }
  2363.  
  2364. //
  2365. // LoadString variation with better control over which language
  2366. // will be selected.
  2367. //
  2368. // The language search order is not consistent between Win95 and
  2369. // NT with the LoadString API, and neither of them really give us 
  2370. // the control that we want.  The language search order that this
  2371. // function will use is roughly:
  2372. //
  2373. //  1. An exact primary/sub language match.
  2374. //  2. A primary language match.
  2375. //  3. English.
  2376. //
  2377. // We manually grok the resource table resources here.  Each 
  2378. // resource table contains 16 entries, some of which may contain
  2379. // empty strings.  All strings are Unicode, are length prefixed 
  2380. // with a WORD containing the number of Unicode characters in the
  2381. // string, and are NOT null terminated.
  2382. // 
  2383. // Note that this is mostly a copy of the real LoadString from the
  2384. // Win95 kernel.
  2385. // 
  2386.  
  2387. INT VMLoadString(
  2388.     HINSTANCE hModule,
  2389.     UINT      wStringID,
  2390.     LPSTR     pszBuffer,
  2391.     int       cchBufferMax,
  2392.     WORD      wLanguage)
  2393. {
  2394.     LPWSTR  pwsz = NULL;
  2395.     int     cb   = 0;
  2396.     int     cch;
  2397.  
  2398.     if ( !pszBuffer || (cchBufferMax-- == 0) )
  2399.     {
  2400.         SetLastError(ERROR_INVALID_PARAMETER);
  2401.         return 0;
  2402.     }
  2403.  
  2404.     // Transform the string ID into the corresponding 
  2405.     // StringTable ID.
  2406.     
  2407.     LPCSTR TableID = (LPCTSTR)((LONG)(((USHORT)(wStringID) >> 4) + 1));
  2408.  
  2409.     cch  = 0;
  2410.     pwsz = (LPWSTR)VMGetResource(hModule,RT_STRING,TableID,wLanguage);
  2411.  
  2412.     if ( pwsz )
  2413.     {
  2414.         __try
  2415.         {
  2416.             wStringID &= 0x0F;
  2417.  
  2418.             while ( TRUE )
  2419.             {
  2420.                 cch = *(pwsz++);
  2421.  
  2422.                 if ( wStringID-- == 0 )
  2423.                     break;
  2424.  
  2425.                 pwsz += cch;
  2426.             }
  2427.  
  2428.             if ( cch > cchBufferMax )
  2429.                 cch = cchBufferMax;
  2430.  
  2431.             cb = WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,pwsz,cch,
  2432.                 pszBuffer,cchBufferMax,NULL,NULL);
  2433.         }
  2434.         __except( EXCEPTION_EXECUTE_HANDLER )
  2435.         {
  2436.             SetLastError(ERROR_BAD_FORMAT);
  2437.         }
  2438.     }
  2439.  
  2440.     pszBuffer[cb] = '\0';
  2441.     
  2442.     return cb;
  2443. }
  2444.  
  2445.  
  2446.