home *** CD-ROM | disk | FTP | other *** search
/ Chip Special: HTML & Java / Chip-Special_1997-01_HTML-a-Java.bin / javasdk / sdk-java.exe / SDKJava.cab / Samples / jexegen / stub / stub.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-10  |  15.4 KB  |  586 lines

  1. /*
  2.  * stub.cpp
  3.  *
  4.  * Sample code.
  5.  *  
  6.  * (C) Copyright 1996, Microsoft Corporation and it suppliers.
  7.  */
  8.  
  9. #pragma hdrstop
  10.  
  11. #include "stub.h"
  12.  
  13. // Macros
  14.  
  15. #define WIN32_ERROR_TO_HRESULT(err)    MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, (err))
  16. #define WIN32_RESULT_TO_HRESULT(err)   ((err) == ERROR_SUCCESS ? S_OK : WIN32_ERROR_TO_HRESULT(err))
  17. #define LAST_WIN32_ERROR_TO_HRESULT()  WIN32_RESULT_TO_HRESULT(GetLastError())
  18.  
  19. // Resource IDs for the class resource data and the main class name data.
  20. // These are the IDs of the resources that jexegen will create when used
  21. // with the /bindto option.
  22.  
  23. #define CLASSRESOURCEID         1000
  24. #define MAINCLASSNAMERESOURCEID 1001
  25.  
  26. //------------------------------------------------------------------------------
  27. // CJView::CJView:
  28. //    Constructor
  29. //------------------------------------------------------------------------------
  30.  
  31. CJView::CJView (int ac, char **av) : m_ac (ac), m_av (av)
  32. {
  33.     m_pszClassName = NULL;
  34.     m_ppszArgs     = NULL;
  35.     m_iArgs        = 0;
  36.     m_pJE          = NULL;
  37. }
  38.  
  39. //------------------------------------------------------------------------------
  40. // CJView::~CJView:
  41. //    Destructor
  42. //------------------------------------------------------------------------------
  43.  
  44. CJView::~CJView ()
  45. {
  46.     if (m_ppszArgs)
  47.     {
  48.         INT n = 0;
  49.  
  50.         while (m_ppszArgs[n] != NULL)
  51.             delete [] m_ppszArgs[n++];
  52.         delete [] m_ppszArgs;
  53.     }
  54.  
  55.     if (m_pJE)
  56.     {
  57.         m_pJE->Release();
  58.         CoUninitialize();
  59.     }
  60. }
  61.  
  62. //------------------------------------------------------------------------------
  63. // CJView::m_FatalError:
  64. //
  65. // Print a formatted error message to stderr
  66. //
  67. // Returns: Nothing
  68. //------------------------------------------------------------------------------
  69.  
  70. void CJView::m_FatalError
  71. (
  72.     INT idString,
  73.     ...
  74. )
  75. {
  76.     CHAR szFmt[BUFSIZE];
  77.     va_list va;
  78.     va_start(va, idString);
  79.  
  80.     LoadString(NULL, IDS_ERROR, szFmt, sizeof(szFmt));
  81.     fprintf(stderr, szFmt);
  82.  
  83.     if (idString)
  84.         LoadString(NULL, idString, szFmt, sizeof(szFmt));
  85.     else
  86.         lstrcpy(szFmt, "%s");
  87.  
  88.     vfprintf(stderr, szFmt, va);
  89.     va_end(va);
  90.     fprintf(stderr, "\n");
  91. }
  92.  
  93. //------------------------------------------------------------------------------
  94. // CJView::m_FatalErrorHR:
  95. //
  96. //      Print a formatted error followup by an hresult tp stderr
  97. //------------------------------------------------------------------------------
  98.  
  99. void CJView::m_FatalErrorHR
  100. (
  101.     HRESULT hr,
  102.     INT     idString,
  103.     ...
  104. )
  105. {
  106.     CHAR  szFmt[BUFSIZE];
  107.     CHAR  buf[BUFSIZE];
  108.     DWORD res;
  109.     va_list va;
  110.     va_start(va, idString);
  111.  
  112.     LoadString(NULL, IDS_ERROR, szFmt, sizeof(szFmt));
  113.     fprintf(stderr, szFmt);
  114.     LoadString(NULL, idString, szFmt, sizeof(szFmt));
  115.     vfprintf(stderr, szFmt, va);
  116.     va_end(va);
  117.  
  118.     res = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  119.                         NULL,
  120.                         (DWORD)hr,
  121.                         LOCALE_SYSTEM_DEFAULT,
  122.                         buf,
  123.                         sizeof(buf),
  124.                         NULL);
  125.  
  126.     CHAR szNoMain[BUFSIZE] = "";
  127.  
  128.     if (!res)
  129.     {
  130.         CHAR szSCODE[BUFSIZE];
  131.  
  132.         LoadString(NULL, IDS_SCODE, szSCODE, sizeof(szSCODE));
  133.         sprintf(buf, szSCODE, (DWORD)hr);
  134.     }
  135.     else
  136.     {
  137.         // Now we check if the error is "Member not found", and if it is, we
  138.         // will append some additional info to the error message letting
  139.         // the user know it was main() that could not be found, since that
  140.         // is the only time this message should be generated.
  141.         
  142.         if (hr == DISP_E_MEMBERNOTFOUND)
  143.         {
  144.             CHAR sz[BUFSIZE] = "";
  145.  
  146.             LoadString(NULL, IDS_NOMAIN, sz, sizeof(sz));
  147.             sprintf(szNoMain, sz, m_pszClassName, m_pszClassName);
  148.         }
  149.         else
  150.             *szNoMain = '\0';
  151.     }
  152.  
  153.  
  154.     fprintf(stderr, ": %s\n", buf);
  155.     if (*szNoMain)
  156.         fprintf(stderr, "%s", szNoMain);
  157. }
  158.  
  159. //------------------------------------------------------------------------------
  160. // CJView::m_InitComAndJava:
  161. //
  162. // Initializes COM and obtains the neccessary interfaces from the Java VM
  163. //
  164. // Returns: TRUE if successful, FALSE if not
  165. //------------------------------------------------------------------------------
  166.  
  167. BOOL CJView::m_InitComAndJava ()
  168. {
  169.     HRESULT           hr   = E_UNEXPECTED;
  170.     IClassFactory    *pcf  = NULL;
  171.  
  172.     hr = CoInitialize(NULL);
  173.  
  174.     if (FAILED(hr))
  175.     {
  176.         m_FatalErrorHR(hr, IDS_COULDNOTINITOLE);
  177.     }
  178.     else
  179.     {
  180.         hr = CoGetClassObject(CLSID_JavaExecute,
  181.                               CLSCTX_INPROC_SERVER |
  182.                               CLSCTX_INPROC_HANDLER |
  183.                               CLSCTX_LOCAL_SERVER,
  184.                               NULL,
  185.                               IID_IClassFactory,
  186.                               (LPVOID*)(&pcf));
  187.         if (FAILED(hr))
  188.         {
  189.             m_FatalErrorHR(hr, IDS_JAVAVM);
  190.         }
  191.         else
  192.         {
  193.             hr = pcf->CreateInstance(NULL, IID_IJavaExecute2, (LPVOID *)(&m_pJE));
  194.             if (FAILED(hr))
  195.             {
  196.                 m_pJE = NULL;
  197.                 m_FatalErrorHR(hr, IDS_CLASSLOADER);
  198.             }
  199.  
  200.             pcf->Release();
  201.         }
  202.  
  203.         if (NULL == m_pJE)
  204.             CoUninitialize();
  205.     }
  206.  
  207.     return (m_pJE != NULL);
  208. }
  209.  
  210. //------------------------------------------------------------------------------
  211. // CJView::MB2WC:
  212. //
  213. //   Converts the multibyte string to a UNICODE string, allocating space
  214. // for the destination string.
  215. //
  216. // Returns: Pointer to newly allocated and converted string, NULL if it fails
  217. //------------------------------------------------------------------------------
  218.  
  219. LPWSTR CJView::m_MB2WC
  220. (
  221.     LPCSTR szAnsi,
  222.     int    cchAnsi
  223. )
  224. {
  225.    // First, determine size of converted string
  226.    LPWSTR pwsz    = NULL;
  227.    int    cchWide = MultiByteToWideChar(0, 0, szAnsi, cchAnsi, NULL, 0) + 1;
  228.  
  229.    if (cchWide > 0)
  230.    {
  231.        // Got size so allocate the space and convert the string
  232.        if (pwsz = new WCHAR[cchWide])
  233.           MultiByteToWideChar(0, 0, szAnsi, cchAnsi, pwsz, cchWide);
  234.     }
  235.  
  236.    return pwsz;
  237. }
  238.  
  239. //------------------------------------------------------------------------------
  240. // CJView::m_WC2MB:
  241. //
  242. //   Converts the given UNICODE string to a multibyte string, allocating space
  243. // for the destination string.
  244. //
  245. // Returns: Pointer to newly allocated and converted string, NULL if it fails
  246. //------------------------------------------------------------------------------
  247.  
  248. LPSTR CJView::m_WC2MB
  249. (
  250.    LPCWSTR pwsz,
  251.    int     cchWide
  252. )
  253. {
  254.    // First, determine size of converted string
  255.    LPSTR psz     = NULL;
  256.    int   cchAnsi = WideCharToMultiByte(0, 0, pwsz, cchWide, NULL, 0, NULL, NULL);
  257.  
  258.    if (cchAnsi > 0)
  259.    {
  260.        // Got size so allocate the space and convert the string
  261.       if (psz = new CHAR[cchAnsi])
  262.           WideCharToMultiByte(0, 0, pwsz, cchWide, psz, cchAnsi, NULL, NULL);
  263.     }
  264.  
  265.     return psz;
  266. }
  267.  
  268. //------------------------------------------------------------------------------
  269. // CJView::m_ParseParameters
  270. //
  271. // Parses off the command line arguments following the class simply
  272. // copying them into a list of OLESTRS
  273. //
  274. // Returns: TRUE if successful, FALSE if not
  275. //------------------------------------------------------------------------------
  276.  
  277. BOOL CJView::m_ParseParameters()
  278. {
  279.     m_iArgs = m_ac - 1;
  280.  
  281.     m_ppszArgs = new LPOLESTR[m_iArgs + 1];
  282.     if (!m_ppszArgs)
  283.     {
  284.         m_FatalError(IDS_OUTOFMEMORY);
  285.         return FALSE;
  286.     }
  287.  
  288.     (m_ppszArgs)[0] = NULL; // Initially empty!
  289.  
  290.     // Now, run through the list of arguments and process
  291.     int iNext = 1;
  292.     int i;
  293.  
  294.     for (i = 0; i < m_iArgs; i++)
  295.     {
  296.         if (!((m_ppszArgs)[i] = m_MB2WC(m_av[iNext++])))
  297.             break;
  298.     }
  299.  
  300.     // If succesful, mark end of array
  301.     if (i == m_iArgs)
  302.     {
  303.         (m_ppszArgs)[i] = NULL;
  304.     }
  305.     else
  306.     {
  307.         // Clean up if we fail
  308.         int n;
  309.  
  310.         for (n = 0; n < i; n++)
  311.             deleteSZ(m_ppszArgs[n]);
  312.         deleteSZ(m_ppszArgs);
  313.     }
  314.  
  315.     return (i == m_iArgs);
  316. }
  317.  
  318. //------------------------------------------------------------------------------
  319.  
  320. BOOL CJView::LoadDataResource( DWORD dwResID, BYTE *pBuffer, DWORD *pdwSize )
  321. {
  322.    HMODULE hMod = GetModuleHandle(NULL);
  323.    DWORD   dwBufferSize;
  324.    HRSRC   hRes;
  325.    HANDLE  hLoadedRes;
  326.    PVOID   pData;
  327.    
  328.    if ( !pdwSize || !pBuffer )
  329.       return FALSE;
  330.  
  331.    dwBufferSize = *pdwSize;
  332.    *pdwSize = 0;
  333.    
  334.    hRes = FindResource( hMod, MAKEINTRESOURCE(dwResID), RT_RCDATA );
  335.  
  336.    if ( hRes == NULL )
  337.       return FALSE;
  338.  
  339.    *pdwSize = SizeofResource( hMod, hRes );
  340.  
  341.    if ( dwBufferSize < *pdwSize )
  342.       return FALSE;
  343.  
  344.    hLoadedRes = LoadResource( hMod, hRes );
  345.  
  346.    if ( !hLoadedRes )
  347.       return FALSE;
  348.  
  349.    pData = LockResource( hLoadedRes );
  350.  
  351.    CopyMemory( pBuffer, pData, *pdwSize );
  352.  
  353.    FreeResource( hLoadedRes );
  354.    
  355.    return TRUE;
  356. }
  357.  
  358. //------------------------------------------------------------------------------
  359. // CJView::Initialize:
  360. //
  361. //  Performs initialization for CJView
  362. //
  363. // Returns: TRUE if successful, FALSE if not
  364. //------------------------------------------------------------------------------
  365.  
  366. BOOL CJView::Initialize ()
  367. {
  368.    // Load the name of the main class file to
  369.    // execute.
  370.    
  371.    char  szBuffer[1024];
  372.    DWORD dwSize = sizeof(szBuffer);
  373.  
  374.    if ( !LoadDataResource( MAINCLASSNAMERESOURCEID, (BYTE *)szBuffer, &dwSize ) )
  375.    {  
  376.       m_FatalError( IDS_NOCLASSGIVEN );
  377.       return FALSE;
  378.    }
  379.    
  380.    m_pszClassName = new char[ lstrlen(szBuffer) + 1];
  381.  
  382.    if ( !m_pszClassName )
  383.    {
  384.       m_FatalError( IDS_OUTOFMEMORY );
  385.       return FALSE;
  386.    }
  387.  
  388.    lstrcpy( m_pszClassName, szBuffer );
  389.  
  390.    return m_InitComAndJava();
  391. }
  392.  
  393. //------------------------------------------------------------------------------
  394. // RunMessageLoop:
  395. //      Message pump for OLE
  396. //------------------------------------------------------------------------------
  397.  
  398. UINT RunMessageLoop(void)
  399. {
  400.     MSG msg;
  401.  
  402.     // No accelerators to load.  Get and dispatch messages until a WM_QUIT
  403.     // message is received.
  404.     ZeroMemory(&msg, sizeof(msg));
  405.  
  406.     msg.wParam = S_OK;
  407.  
  408.     while (GetMessage(&msg, NULL, 0, 0))
  409.       //
  410.       // Dispatch message to target window.
  411.       //
  412.       // We don't have any windows, so there are no window procedures that
  413.       // require TranslateMessage(&msg).
  414.       //
  415.       DispatchMessage(&msg);
  416.  
  417.     return(msg.wParam);
  418. }
  419.  
  420. //------------------------------------------------------------------------------
  421. // CJView::ExecuteClass:
  422. //
  423. //  Executes the given class file
  424. //
  425. // Returns: 0 if successful, 1 if not
  426. //------------------------------------------------------------------------------
  427.  
  428. DWORD _stdcall RunClassThread
  429. (
  430.     PVOID pv
  431. )
  432. {
  433.     CJView* pJV     = (CJView*)pv;
  434.     HRESULT hr;
  435.     int     iResult;
  436.  
  437.     if ( pJV->m_ParseParameters() )
  438.     {
  439.         // Tell the VM that it should look in the current module for 
  440.         // class files.  The /bindto option of the jexegen tool will 
  441.         // place the resource data in the exe with a resource ID of 
  442.         // 1001 so we tell the VM that is where the data is.
  443.     
  444.         JAVACLASSRESOURCEINFO jcri;
  445.         jcri.hModule      = GetModuleHandle(NULL);
  446.         jcri.dwResourceID = CLASSRESOURCEID;     // Compatible with jexegen.
  447.       
  448.         hr = pJV->m_pJE->SetClassSource( CLASS_SOURCE_TYPE_MODULERESOURCES, 
  449.                                          &jcri, 
  450.                                          sizeof(JAVACLASSRESOURCEINFO) );
  451.  
  452.         if ( !SUCCEEDED(hr) )
  453.         {
  454.            pJV->m_FatalError( IDS_VMCANTFINDRESOURCE );
  455.            return 0;
  456.         }
  457.         
  458.         // Execute.
  459.         LPOLESTR        pszClassName = pJV->m_MB2WC(pJV->m_pszClassName);
  460.         LPERRORINFO     pIErrorInfo = NULL;
  461.         JAVAEXECUTEINFO jei;
  462.  
  463.         jei.cbSize       = sizeof(jei);
  464.         jei.dwFlags      = 0;
  465.         jei.pszClassName = pszClassName;
  466.         jei.rgszArgs     = (LPCOLESTR *)(pJV->m_ppszArgs);
  467.         jei.cArgs        = pJV->m_iArgs;
  468.         jei.pszClassPath = NULL;
  469.  
  470.         hr = pJV->m_pJE->Execute(&jei, &pIErrorInfo);
  471.  
  472.         if (!SUCCEEDED(hr))
  473.         {
  474.             // Most likely .class file did not exist
  475.             pJV->m_FatalErrorHR (hr, IDS_EXECUTINGCLASS, pJV->m_pszClassName);
  476.             iResult = 1;
  477.         }
  478.         else if (pIErrorInfo)
  479.         {
  480.             // VM threw an exception while running the .class file.  We
  481.             // get the info via the returned IErrorInfo interface
  482.             BSTR bstrError = NULL;
  483.  
  484.             if (SUCCEEDED(pIErrorInfo->GetDescription(&bstrError)))
  485.             {
  486.                 LPSTR pszError = pJV->m_WC2MB(bstrError);
  487.  
  488.                 if (pszError)
  489.                 {
  490.                     pJV->m_FatalError (0, pszError);
  491.                     deleteSZ(pszError);
  492.                 }
  493.                 else
  494.                     pJV->m_FatalError (IDS_UNKNOWNERROR);
  495.  
  496.                 SysFreeString(bstrError);
  497.             }
  498.             else
  499.                 pJV->m_FatalError(IDS_UNKNOWNERROR);
  500.  
  501.             iResult = 1;
  502.  
  503.             pIErrorInfo->Release();
  504.         }
  505.         else
  506.             // Success.
  507.             iResult = 0;
  508.  
  509.         deleteSZ(pszClassName);
  510.     }
  511.     else
  512.         iResult = 1;
  513.  
  514.     // Terminate message pump
  515.     PostThreadMessage(pJV->m_dwMsgLoopThreadID, WM_QUIT, 0, 0);
  516.  
  517.     return (DWORD)iResult;
  518. }
  519.  
  520. //------------------------------------------------------------------------------
  521.  
  522. int __cdecl main
  523. (
  524.     int    ac,
  525.     char **av
  526. )
  527. {
  528.     int     iRet = 1;
  529.     CJView* pJV  = new CJView(ac, av);
  530.  
  531.     if ( !pJV )
  532.     {
  533.         CHAR szFmt[20];
  534.  
  535.         LoadString(NULL, IDS_ERROR, szFmt, sizeof(szFmt));
  536.         fprintf(stderr, szFmt);
  537.         LoadString(NULL, IDS_OUTOFMEMORY, szFmt, sizeof(szFmt));
  538.         fprintf(stderr, szFmt);
  539.         fprintf(stderr, "\n");
  540.         return iRet;
  541.     }
  542.  
  543.     if (pJV->Initialize())
  544.     {
  545.         // OK, we're ready, everything is done on the applet thread
  546.         HANDLE hth;
  547.         DWORD  dwThreadID;
  548.  
  549.         pJV->m_dwMsgLoopThreadID = GetCurrentThreadId();
  550.         hth = CreateThread(NULL, 0, &RunClassThread, pJV, 0, &dwThreadID);
  551.  
  552.         if (hth)
  553.         {
  554.             RunMessageLoop();
  555.  
  556.             // If we returned from RunMessageLoop() as a result of
  557.             // RunClassThread() posting the WM_QUIT message, then the thread
  558.             // will be exiting shortly (if not already).  We wait for it to
  559.             // terminate and grab its exit code.  1/2 second is plenty --
  560.             // if the thread doesn't die by then, something is wrong (we
  561.             // got a quit message from someone else, perhaps?) in which case
  562.             // we return 1 for failure.
  563.  
  564.             if (WaitForSingleObject (hth, 500) == WAIT_OBJECT_0)
  565.             {
  566.                 DWORD   dwRetCode = 1;
  567.  
  568.                 // Thread's dead, baby... thread's dead...
  569.                 GetExitCodeThread (hth, &dwRetCode);
  570.                 iRet = dwRetCode;
  571.             }
  572.             CloseHandle(hth);
  573.             hth = NULL;
  574.         }
  575.         else
  576.         {
  577.             pJV->m_FatalErrorHR(LAST_WIN32_ERROR_TO_HRESULT(),
  578.                                 IDS_NOJAVATHREAD);
  579.         }
  580.     }
  581.  
  582.     delete pJV;
  583.     return iRet;
  584. }
  585.  
  586.