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