home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 39 / IOPROG_39.ISO / SOFT / sdkjava40.exe / data1.cab / fg_Samples / Samples / COM / jexegen / stub / dllstub.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-04  |  30.4 KB  |  1,036 lines

  1. /*++
  2.  
  3. Copyright (c) 1996-1999  Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     dllstub.cpp
  8.  
  9. Abstract:
  10.  
  11.     generic Java/COM DLL stub.
  12.  
  13. --*/
  14.  
  15.  
  16. #include <string.h>
  17.  
  18. #pragma intrinsic(memcmp)
  19.  
  20. #pragma warning(disable:4514)   // "unreferenced inline function" warning
  21.  
  22. #pragma warning(disable:4201)   // "nameless struct/union" warning
  23. #include <windows.h>
  24. #pragma warning(default:4201)   // "nameless struct/union" warning
  25.  
  26. #include "jpcommon.h"
  27. #include "jpsplit.h"
  28. #include "util.h"
  29.  
  30. #include <initguid.h>
  31. #include "javaax.h"
  32.  
  33.  
  34. //----------------------------------------------------------------
  35. // Constants
  36. //----------------------------------------------------------------
  37.  
  38. #define BUFSIZE     512 // A one-size fits all buffer size...
  39.  
  40. // # chars in guid (including null terminator.)
  41. #define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  42.  
  43. // General strings that are useful.
  44. const CHAR achCLSID[]           = "CLSID";
  45. const CHAR achProgID[]          = "ProgID";
  46. const CHAR achInprocServer32[]  = "InprocServer32";
  47. const CHAR achControl[]         = "Control";
  48. const CHAR achJavaClass[]       = "JavaClass";
  49. const CHAR achCodeBase[]        = "CodeBase";
  50. const CHAR achThreadingModel[]  = "ThreadingModel";
  51. const CHAR achBoth[]            = "Both";
  52. const CHAR achApartment[]       = "Apartment";
  53. const CHAR achFree[]            = "Free";
  54. const CHAR achNeutral[]         = "Neutral";
  55. CHAR       g_szMSJAVAPath[_MAX_PATH];
  56.  
  57.  
  58. // {BE0975F0-BBDD-11cf-97DF-00AA001F73C1}
  59. const GUID TYPEID_JavaClasses  =
  60. { 0xbe0975f0, 0xbbdd, 0x11cf, { 0x97, 0xdf, 0x0, 0xaa, 0x0, 0x1f, 0x73, 0xc1 } };
  61.  
  62. //----------------------------------------------------------------
  63. // Types
  64. //----------------------------------------------------------------
  65.  
  66. #if defined(_WIN64)
  67.     typedef __int64 LONG_PTR, *PLONG_PTR;
  68.     typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
  69. #else
  70.     typedef long LONG_PTR, *PLONG_PTR;
  71.     typedef unsigned long ULONG_PTR, *PULONG_PTR;
  72. #endif
  73.  
  74.  
  75. class MyClassFactory : public IClassFactory
  76. {
  77. public:
  78.     // Allocation/free
  79.     void * operator new(size_t cb)
  80.       { return HeapAlloc(GetProcessHeap(), 0, cb); }
  81.     void operator delete(void * pv)
  82.       { HeapFree(GetProcessHeap(), 0, pv); }
  83.     __declspec(nothrow) MyClassFactory()
  84.       {}
  85.  
  86.     // IUnknown methods
  87.     virtual STDMETHODIMP            QueryInterface( REFIID riid, LPVOID* ppv );
  88.     virtual STDMETHODIMP_(ULONG)    AddRef( void );
  89.     virtual STDMETHODIMP_(ULONG)    Release( void );
  90.     // IClassFactory methods
  91.     virtual STDMETHODIMP    CreateInstance( IUnknown* pUnkOuter, REFIID riid,
  92.         LPVOID* ppvObject );
  93.     virtual STDMETHODIMP    LockServer( BOOL fLock );
  94. };
  95.  
  96.  
  97. //----------------------------------------------------------------
  98. // Global Variables
  99. //----------------------------------------------------------------
  100.  
  101. BOOL                 g_fInitialized = FALSE;
  102. CRITICAL_SECTION     g_CriticalSection;
  103. HINSTANCE            g_hModuleMine = NULL;
  104. char                 g_szFileName[BUFSIZE];
  105. BOOL                 g_fTypeLibError = FALSE;
  106. HCRIDATA             g_hCRIData = NULL;
  107. ULONG                g_dwUseCount = 0;
  108. ULONG                g_dwLockCount = 0;
  109. MyClassFactory       *g_pMyClassFactory;
  110. IJavaComModuleManager   *g_pModuleManager = NULL;
  111.  
  112.  
  113. //----------------------------------------------------------------
  114. // We don't link with CRT for size reasons--must define this.
  115. //----------------------------------------------------------------
  116. int
  117. __cdecl
  118. _purecall()
  119. {
  120.     DebugBreak();
  121.     return 0;
  122. }
  123.  
  124. //----------------------------------------------------------------
  125. // InitializeDll()
  126. //----------------------------------------------------------------
  127. HRESULT
  128. InitializeDll( void )
  129. {
  130.     // Rarely, several threads may attempt to call this routine simultaneously
  131.  
  132.     HRESULT hr = NOERROR;
  133.  
  134.     EnterCriticalSection( &g_CriticalSection );
  135.  
  136.     if ( !g_fInitialized ) {
  137.  
  138.         g_pMyClassFactory = new MyClassFactory();
  139.         if (!g_pMyClassFactory)
  140.             hr = E_OUTOFMEMORY;
  141.  
  142.         if (SUCCEEDED(hr) && g_pModuleManager == NULL) {
  143.             hr = CoCreateInstance(CLSID_StdJavaComModuleManager, NULL,
  144.                 CLSCTX_INPROC_SERVER, IID_IJavaComModuleManager, (LPVOID *)
  145.                 &g_pModuleManager);
  146.         }
  147.  
  148.         if (SUCCEEDED(hr))
  149.             g_fInitialized = TRUE;
  150.     }
  151.  
  152.     LeaveCriticalSection( &g_CriticalSection );
  153.     return hr;
  154. }
  155.  
  156. //----------------------------------------------------------------
  157. // LoadCRIData()
  158. //----------------------------------------------------------------
  159. void
  160. LoadCRIData( void )
  161. {
  162.     EnterCriticalSection( &g_CriticalSection );
  163.  
  164.     g_hCRIData = CRIOpenData( g_hModuleMine, JEX_DEFAULT_CRI_RESOURCE_ID );
  165.  
  166.     LeaveCriticalSection( &g_CriticalSection );
  167.  
  168. }
  169.  
  170. //----------------------------------------------------------------
  171. // GetVMPath() - get path to VM DLL.
  172. //----------------------------------------------------------------
  173. void
  174. GetVMPath( void )
  175. {
  176.     BOOL    fGotIt = FALSE;
  177.     LONG    cb = sizeof( g_szMSJAVAPath );
  178.     LONG    nResult;
  179.  
  180.     nResult = RegQueryValue( HKEY_CLASSES_ROOT,
  181.         "CLSID\\{3EFB1800-C2A1-11CF-960C-0080C7C2BA87}\\InprocServer32",
  182.         g_szMSJAVAPath, &cb );
  183.  
  184.     if( ERROR_SUCCESS == nResult ) {
  185.         if( GetFileAttributes( g_szMSJAVAPath ) != 0xFFFFFFFF )
  186.             fGotIt = TRUE;
  187.     }
  188.  
  189.     if( !fGotIt )
  190.         lstrcpy( g_szMSJAVAPath, "msjava.dll" );
  191. }
  192.  
  193.  
  194. //----------------------------------------------------------------
  195. // MyDeleteKey() - delete a key and subkeys.
  196. //----------------------------------------------------------------
  197. void
  198. MyDeleteKey(
  199.     HKEY        hKey,
  200.     const char  *pszName )
  201. {
  202.     HKEY    hKey2;
  203.     char    szSubkey[BUFSIZE];
  204.     DWORD   dwLen;
  205.     LONG    nResult;
  206.  
  207.     nResult = RegOpenKeyEx( hKey, pszName, 0, KEY_ALL_ACCESS, &hKey2 );
  208.     if ( ERROR_SUCCESS != nResult )
  209.         return;
  210.  
  211.     for (;;) {
  212.         dwLen = BUFSIZE;
  213.         nResult = RegEnumKeyEx( hKey2, 0, szSubkey, &dwLen, NULL, NULL,
  214.             NULL, NULL );
  215.         if ( ERROR_SUCCESS != nResult )
  216.             break;
  217.  
  218.         MyDeleteKey( hKey2, szSubkey );
  219.     }
  220.  
  221.     RegCloseKey( hKey2 );
  222.  
  223.     RegDeleteKey( hKey, pszName );
  224. }
  225.  
  226.  
  227. /*
  228.  * Register the given Java class in the registry by adding the correct
  229.  *  registry keys.
  230.  */
  231. BOOL
  232. RegisterOneClass(
  233.     LPCSTR  szJavaClass,    // must be in dotted form
  234.     LPCSTR  szClsid,
  235.     LPCSTR  szProgID,
  236.     LPCSTR  szDesc,
  237.     LPCSTR  szTypeLib,
  238.     WORD    verMajor,
  239.     WORD    verMinor,
  240.     LPCSTR  szServer,
  241.     DWORD   dwFlags )
  242. {
  243.    HKEY    hKey  = NULL;
  244.    HKEY    hKey2 = NULL;
  245.    HKEY    hKey3 = NULL;
  246.    HKEY    hKey4 = NULL;
  247.    DWORD   result;
  248.    BOOL    fRet = FALSE;
  249.    LPCSTR  pcszThreadingModelValue;
  250.  
  251.    // If we fail in the middle, the state of the registry entries
  252.    // is indeterminate (as per OLE specs).
  253.  
  254.    // HKEY_CLASSES_ROOT\{progid} = {description}
  255.    result = RegCreateKey(HKEY_CLASSES_ROOT, szProgID, &hKey);
  256.    if (result != ERROR_SUCCESS)       goto lExit;
  257.    result = RegSetValue(hKey, NULL, REG_SZ, szDesc, lstrlen(szDesc)+1);
  258.    if (result != ERROR_SUCCESS)       goto lExit;
  259.  
  260.    // HKEY_CLASSES_ROOT\{progid}\CLSID = {clsid}
  261.    result = RegCreateKey(hKey, achCLSID, &hKey2);
  262.    if (result != ERROR_SUCCESS)       goto lExit;
  263.    result = RegSetValue(hKey2, NULL, REG_SZ, szClsid, GUIDSTR_MAX);
  264.    if (result != ERROR_SUCCESS)       goto lExit;
  265.  
  266.    RegCloseKey(hKey);
  267.    RegCloseKey(hKey2);
  268.    hKey = NULL;
  269.    hKey2 = NULL;
  270.  
  271.    // Create HKEY_CLASSES_ROOT\CLSID
  272.    result = RegCreateKey(HKEY_CLASSES_ROOT, achCLSID, &hKey);
  273.    if (result != ERROR_SUCCESS)       goto lExit;
  274.  
  275.    // HKEY_CLASSES_ROOT\CLSID\{clsid} = {description}
  276.    // Remove the key and all subkeys first...
  277.    MyDeleteKey(hKey, szClsid);
  278.    result = RegCreateKey(hKey, szClsid, &hKey2);
  279.    if (result != ERROR_SUCCESS)       goto lExit;
  280.    result = RegSetValue(hKey2, NULL, REG_SZ, szDesc, lstrlen(szDesc)+1);
  281.    if (result != ERROR_SUCCESS)       goto lExit;
  282.  
  283.    // HKEY_CLASSES_ROOT\CLSID\{clsid}\InprocServer32 = {server}
  284.    result = RegCreateKey(hKey2, achInprocServer32, &hKey3);
  285.    if (result != ERROR_SUCCESS)       goto lExit;
  286.    result = RegSetValue(hKey3, NULL, REG_SZ, szServer, lstrlen(szServer)+1);
  287.    if (result != ERROR_SUCCESS)       goto lExit;
  288.  
  289.    // HKEY_CLASSES_ROOT\CLSID\{clsid}\InprocServer32\ThreadingModel =
  290.    //  {Both,Free,Apartment,Neutral}
  291.    if( dwFlags & DLLREG_TM_APARTMENT ) {
  292.       pcszThreadingModelValue = (LPCSTR)achApartment;
  293.    } else if( dwFlags & DLLREG_TM_FREE ) {
  294.       pcszThreadingModelValue = (LPCSTR)achFree;
  295.    } else if( dwFlags & DLLREG_TM_BOTH ) {
  296.       pcszThreadingModelValue = (LPCSTR)achBoth;
  297.    } else if( dwFlags & DLLREG_TM_NEUTRAL ) {
  298.       pcszThreadingModelValue = (LPCSTR)achNeutral;
  299.    } else if( dwFlags & DLLREG_CONTROL ) {
  300.       // default ThreadingModel for controls is "Apartment".
  301.       pcszThreadingModelValue = (LPCSTR)achApartment;
  302.    } else {
  303.       // default ThreadingModel for non-controls is "Both".
  304.       pcszThreadingModelValue = (LPCSTR)achBoth;
  305.    }
  306.  
  307.    result = RegSetValueEx(hKey3, achThreadingModel, 0, REG_SZ,
  308.       (BYTE*)pcszThreadingModelValue, lstrlen(pcszThreadingModelValue)+1);
  309.    if (result != ERROR_SUCCESS)       goto lExit;
  310.  
  311.    // HKEY_CLASSES_ROOT\CLSID\{clsid}\InprocServer32\JavaClass = {classname}
  312.    result = RegSetValueEx(hKey3, achJavaClass, 0, REG_SZ, (BYTE*)szJavaClass,
  313.       lstrlen(szJavaClass)+1);
  314.    if (result != ERROR_SUCCESS)       goto lExit;
  315.  
  316.    // HKEY_CLASSES_ROOT\CLSID\{clsid}\InprocServer32\CodeBase -- not used for DLL
  317.  
  318.    RegCloseKey(hKey3);
  319.    hKey3 = NULL;
  320.  
  321.    // HKEY_CLASSES_ROOT\CLSID\{clsid}\progid = {progid}
  322.    result = RegCreateKey(hKey2, achProgID, &hKey3);
  323.    if (result != ERROR_SUCCESS)       goto lExit;
  324.    result = RegSetValue(hKey3, NULL, REG_SZ, szProgID, lstrlen(szProgID)+1);
  325.    if (result != ERROR_SUCCESS)       goto lExit;
  326.    RegCloseKey(hKey3);
  327.    hKey3 = NULL;
  328.  
  329.    if( szTypeLib != NULL ) {
  330.        char szVersion[10];
  331.  
  332.        // HKEY_CLASSES_ROOT\CLSID\{clsid}\TypeLib = {typelib guid}
  333.        result = RegCreateKey(hKey2, "TypeLib", &hKey3);
  334.        if (result != ERROR_SUCCESS)       goto lExit;
  335.        result = RegSetValue(hKey3, NULL, REG_SZ, szTypeLib, lstrlen(szTypeLib) + 1);
  336.        if (result != ERROR_SUCCESS)       goto lExit;
  337.        RegCloseKey( hKey3 );
  338.        hKey3 = NULL;
  339.  
  340.        // HKEY_CLASSES_ROOT\CLSID\{clsid}\Version = {major version}.{minor version}
  341.        wsprintf(szVersion, "%u.%u", verMajor, verMinor);
  342.        result = RegCreateKey(hKey2, "Version", &hKey3);
  343.        if (result != ERROR_SUCCESS)       goto lExit;
  344.        result = RegSetValue(hKey3, NULL, REG_SZ, szVersion, lstrlen(szVersion) + 1);
  345.        if (result != ERROR_SUCCESS)       goto lExit;
  346.        RegCloseKey( hKey3 );
  347.        hKey3 = NULL;
  348.    }
  349.  
  350.    // Register as an OLE control if specified.
  351.    if( dwFlags & DLLREG_CONTROL ) {
  352.        // HKEY_CLASSES_ROOT\CLSID\{clsid}\Control
  353.        result = RegCreateKey(hKey2, achControl, &hKey3);
  354.        if (result != ERROR_SUCCESS)       goto lExit;
  355.  
  356.        // just create the key, nothing else with "Control"
  357.        RegCloseKey( hKey3 );
  358.        hKey3 = NULL;
  359.  
  360.        // HKEY_CLASSES_ROOT\CLSID\{clsid}\ToolboxBitmap32 = {server},1
  361.        char szBitmapPath[MAX_PATH*2];
  362.  
  363.        GetVMPath();
  364.  
  365.        lstrcpyn( szBitmapPath, g_szMSJAVAPath, (ARRAY_ELEMENTS( szBitmapPath ) - 3) );
  366.        lstrcat(szBitmapPath, ",1");
  367.        result = RegCreateKey(hKey2, "ToolboxBitmap32", &hKey3);
  368.        if (result != ERROR_SUCCESS)       goto lExit;
  369.        result = RegSetValue(hKey3, NULL, REG_SZ, szBitmapPath, lstrlen(szBitmapPath)+1);
  370.        if (result != ERROR_SUCCESS)       goto lExit;
  371.        RegCloseKey( hKey3 );
  372.        hKey3 = NULL;
  373.  
  374.        // HKEY_CLASSES_ROOT\CLSID\{clsid}\MiscStatus\1 = {misc status bits}
  375.        char szMiscStatus[16];
  376.        wsprintf(szMiscStatus, "%d", OLEMISC_SETCLIENTSITEFIRST |
  377.           OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_RECOMPOSEONRESIZE |
  378.           OLEMISC_INSIDEOUT );
  379.  
  380.        result = RegCreateKey(hKey2, "MiscStatus\\1", &hKey3);
  381.        if (result != ERROR_SUCCESS)       goto lExit;
  382.        result = RegSetValue(hKey3, NULL, REG_SZ, szMiscStatus, lstrlen(szMiscStatus)+1);
  383.        if (result != ERROR_SUCCESS)       goto lExit;
  384.        RegCloseKey( hKey3 );
  385.        hKey3 = NULL;
  386.    }
  387.  
  388.    // HKEY_CLASSES_ROOT\CLSID\{clsid}\Implemented Categories\{TYPEID_JavaClasses}
  389.    //   Register as a Java Class. Equivalent of
  390.    //     rgcatid[0] = TYPEID_JavaClasses;
  391.    //     ICatRegister::RegisterClassImplCategories(clsid, 1, rgcatid);
  392.    CHAR szCatid[GUIDSTR_MAX];
  393.  
  394.    GUID2StringA(TYPEID_JavaClasses, szCatid);
  395.  
  396.    result = RegCreateKey(hKey2, "Implemented Categories", &hKey3);
  397.    if (result != ERROR_SUCCESS)           goto lExit;
  398.    result = RegCreateKey(hKey3, szCatid, &hKey4);
  399.    if (result != ERROR_SUCCESS)           goto lExit;
  400.    RegCloseKey(hKey4);
  401.    RegCloseKey(hKey3);
  402.    hKey3 = hKey4 = NULL;
  403.  
  404.    fRet = TRUE;
  405.  
  406. lExit:
  407.    if (hKey) {
  408.       RegCloseKey(hKey);
  409.    }
  410.    if (hKey2) {
  411.       RegCloseKey(hKey2);
  412.    }
  413.    if (hKey3) {
  414.       RegCloseKey(hKey3);
  415.    }
  416.    if (hKey4) {
  417.       RegCloseKey(hKey4);
  418.    }
  419.  
  420.    return fRet;
  421. }
  422.  
  423. //----------------------------------------------------------------
  424. // UnregisterOneClass()
  425. //----------------------------------------------------------------
  426. BOOL
  427. UnregisterOneClass(
  428.     const char  *pszClsid,
  429.     const char  *pszProgid )
  430. {
  431.     char szName[BUFSIZE];
  432.  
  433.     lstrcpy( szName, achCLSID);
  434.     lstrcat( szName, "\\" );
  435.     lstrcat( szName, pszClsid );
  436.     MyDeleteKey( HKEY_CLASSES_ROOT, szName );
  437.  
  438.     if ( pszProgid != NULL )
  439.         MyDeleteKey( HKEY_CLASSES_ROOT, pszProgid );
  440.  
  441.     return TRUE;
  442. }
  443.  
  444. /* InvokeUserRegHandler( wszClassName )
  445.  *
  446.  * Attempts to locate the registration method for the given class name.  The
  447.  * registration method is a method matching the following signature, including
  448.  * the name:
  449.  *
  450.  * public static void onCOMRegister( boolean bRegister );
  451.  *
  452.  * If the method is found, it is invoked via RNI interfaces, and the bRegister
  453.  * flag indicates whether the component is being registered or unregistered.
  454.  * The flag is true if registering; false if unregistering.  If the method is
  455.  * not found, the function simply returns.
  456.  */
  457. HRESULT
  458. InvokeUserRegHandler(
  459.     IJavaComModuleManager   *pModuleManager,
  460.     REFCLSID                clsid,
  461.     BOOL                    fRegister )
  462. {
  463.     return pModuleManager->RunRegistrationCode(clsid, g_hModuleMine,
  464.         CLSCTX_INPROC_SERVER, fRegister);
  465. }
  466.  
  467.  
  468. //----------------------------------------------------------------
  469. //  TypeLib
  470. //----------------------------------------------------------------
  471. BOOL
  472. CALLBACK
  473. MyRegisterTypeLib(
  474.     HINSTANCE   hModule,
  475.     LPCTSTR     lpszType,
  476.     LPTSTR      lpszName,
  477.     LONG_PTR    fRegister )
  478. {
  479.     UNREFERENCED_PARAMETER( hModule );
  480.     UNREFERENCED_PARAMETER( lpszType );
  481.  
  482.     CHAR      szName[BUFSIZE];
  483.     WCHAR     wszName[BUFSIZE];
  484.     ITypeLib *ptlb = NULL;
  485.     TLIBATTR *pta = NULL;
  486.     HRESULT   hr;
  487.  
  488.     // Add typelib ID onto end of name.
  489.     if( IS_INTRESOURCE( lpszName ) ) {
  490.         if( (LONG_PTR) lpszName != 1 ) {
  491.             wsprintf(szName, "%s\\%ld", g_szFileName, (long)(LONG_PTR)lpszName);
  492.         } else {
  493.             lstrcpyn( szName, g_szFileName, ARRAY_ELEMENTS( szName ) );
  494.         }
  495.     }
  496.  
  497.     MultiByteToWideChar(CP_ACP, 0, szName, -1, wszName, BUFSIZE );
  498.  
  499.     hr = LoadTypeLib( wszName, &ptlb );
  500.     if ( hr != S_OK ) goto Error;
  501.  
  502.     if ( fRegister ) {
  503.         hr = RegisterTypeLib( ptlb, wszName, NULL );
  504.     } else {
  505.         hr = ptlb->GetLibAttr( &pta );
  506.         if (hr != S_OK ) goto Error;
  507.  
  508.         hr = UnRegisterTypeLib( pta->guid, pta->wMajorVerNum, pta->wMinorVerNum,
  509.             pta->lcid, pta->syskind );
  510.     }
  511.  
  512. Error:
  513.     if ( pta != NULL )
  514.         ptlb->ReleaseTLibAttr( pta );
  515.  
  516.     if ( ptlb != NULL )
  517.         ptlb->Release();
  518.  
  519.     if ( hr != S_OK ) {
  520.         g_fTypeLibError = TRUE;
  521.  
  522.         // NB: we keep enumerating even after reg/unreg failure.
  523.     }
  524.  
  525.     return TRUE;
  526. }
  527.  
  528.  
  529. //----------------------------------------------------------------
  530. // RegistrationCallback()
  531. //----------------------------------------------------------------
  532.  
  533. typedef struct
  534. {
  535.     BOOL                    fRegister;
  536.     IJavaComModuleManager   *pModuleManager;
  537.     IUnknown                **ppunkClassObjects;
  538.     HRESULT                 hr;
  539. } ExtraEnumerationData;
  540.  
  541.  
  542. // NB: this callback does not use the hr field of ExtraEnumerationData.
  543. BOOL
  544. CALLBACK
  545. RegistrationCallback(
  546.     DWORD   iCRIEntry,          // CRI entry index
  547.     LPCWSTR pcwszClassName,
  548.     LPCWSTR pcwszProgID,        // may be NULL
  549.     LPCWSTR pcwszDescription,   // may be NULL
  550.     DWORD   dwFlags,
  551.     REFGUID rguidCLSID,
  552.     REFGUID rguidTypelib,       // may be GUID_NULL, meaning no type library
  553.     WORD    wVerMajor,          // typelib major version
  554.     WORD    wVerMinor,          // typelib minor version
  555.     void    *pvExtra )
  556. {
  557.     BOOL    fRetVal;
  558.     char    pszClassName[2 * MAX_PATH];
  559.     char    pszProgID[2 * MAX_PATH];
  560.     char    pszDescription[2 * MAX_PATH];
  561.     char    szCLSID[GUIDSTR_MAX];
  562.     char    szTypelibGUIDBuffer[GUIDSTR_MAX];
  563.     char    *szTypelibGUID;
  564.     HRESULT hr;
  565.     ExtraEnumerationData    *pExtra;
  566.  
  567.     szTypelibGUID = NULL;
  568.     pExtra = (ExtraEnumerationData *)pvExtra;
  569.  
  570.     //
  571.     // convert strings to MBCS
  572.     //
  573.  
  574.     WideCharToMultiByte(CP_ACP, 0, pcwszClassName, -1, pszClassName,
  575.         ARRAY_ELEMENTS(pszClassName), NULL, NULL);
  576.  
  577.     if (pcwszProgID)
  578.         WideCharToMultiByte(CP_ACP, 0, pcwszProgID, -1, pszProgID,
  579.             ARRAY_ELEMENTS(pszProgID), NULL, NULL);
  580.     else
  581.         pszProgID[0] = '\0';
  582.  
  583.     if (pcwszDescription)
  584.         WideCharToMultiByte(CP_ACP, 0, pcwszDescription, -1, pszDescription,
  585.             ARRAY_ELEMENTS(pszDescription), NULL, NULL);
  586.     else
  587.         pszDescription[0] = '\0';
  588.  
  589.     // ensure that class name is in dotted form.
  590.     AnsiTranslateChars(pszClassName, '/', '.');
  591.  
  592.     // Convert GUIDs to ANSI string version.
  593.     GUID2StringA(rguidCLSID, szCLSID);
  594.  
  595.     if (rguidTypelib != GUID_NULL) {
  596.         GUID2StringA(rguidTypelib, szTypelibGUIDBuffer);
  597.         szTypelibGUID = szTypelibGUIDBuffer;
  598.     }
  599.  
  600.     // Register/Unregister
  601.     if (pExtra->fRegister) {
  602.         fRetVal = RegisterOneClass(pszClassName, szCLSID, pszProgID,
  603.             pszDescription, szTypelibGUID, wVerMajor, wVerMinor,
  604.             g_szFileName, dwFlags);
  605.     } else {
  606.         // load the class object before removing the registry settings.
  607.         hr = pExtra->pModuleManager->GetClassObject(rguidCLSID,
  608.             g_hModuleMine, CLSCTX_INPROC_SERVER, IID_IUnknown,
  609.             (void**)&(pExtra->ppunkClassObjects[iCRIEntry]));
  610.         // We ignore this HR and delete the reg keys anyway...
  611.  
  612.         fRetVal = UnregisterOneClass(szCLSID, pszProgID);
  613.     }
  614.  
  615.     return fRetVal;
  616. }
  617.  
  618. //----------------------------------------------------------------
  619. // UserRegHandlerCallback()
  620. //----------------------------------------------------------------
  621.  
  622. #pragma warning(disable:4100)   // "unreferenced formal parameter" warning
  623.  
  624. BOOL
  625. CALLBACK
  626. UserRegHandlerCallback(
  627.     DWORD   iCRIEntry,          // CRI entry index
  628.     LPCWSTR pcwszClassName,
  629.     LPCWSTR pcwszProgID,        // may be NULL
  630.     LPCWSTR pcwszDescription,   // may be NULL
  631.     DWORD   dwFlags,
  632.     REFGUID rguidCLSID,
  633.     REFGUID rguidTypelib,       // may be GUID_NULL, meaning no type library
  634.     WORD    wVerMajor,          // typelib major version
  635.     WORD    wVerMinor,          // typelib minor version
  636.     void    *pvExtra )
  637. {
  638.     ExtraEnumerationData    *pExtra;
  639.  
  640.     pExtra = (ExtraEnumerationData *)pvExtra;
  641.  
  642.     // if there is a user registration handler, invoke it.
  643.     if (dwFlags & DLLREG_USERREG) {
  644.         pExtra->hr = InvokeUserRegHandler(pExtra->pModuleManager, rguidCLSID,
  645.             pExtra->fRegister);
  646.     }
  647.  
  648.     return( SUCCEEDED( pExtra->hr ) );
  649. }
  650.  
  651. #pragma warning(default:4100)   // "unreferenced formal parameter" warning
  652.  
  653. //----------------------------------------------------------------
  654. // FindCLSIDCallback()
  655. //----------------------------------------------------------------
  656.  
  657. typedef struct
  658. {
  659.     GUID    guidCLSID;
  660.     BOOL    fFoundCLSID;
  661. } FindCLSIDCallbackExtra;
  662.  
  663. #pragma warning(disable:4100)   // "unreferenced formal parameter" warning
  664.  
  665. BOOL
  666. CALLBACK
  667. FindCLSIDCallback(
  668.     DWORD   iCRIEntry,          // CRI entry index
  669.     LPCWSTR pcwszClassName,
  670.     LPCWSTR pcwszProgID,        // may be NULL
  671.     LPCWSTR pcwszDescription,   // may be NULL
  672.     DWORD   dwFlags,
  673.     REFGUID rguidCLSID,
  674.     REFGUID rguidTypelib,       // may be GUID_NULL, meaning no type library
  675.     WORD    wVerMajor,          // typelib major version
  676.     WORD    wVerMinor,          // typelib minor version
  677.     void    *pvExtra )
  678. {
  679.     BOOL                    fRetVal;
  680.     FindCLSIDCallbackExtra  *pExtra;
  681.  
  682.     fRetVal = TRUE;
  683.     pExtra = (FindCLSIDCallbackExtra *)pvExtra;
  684.  
  685.     // if this CRI entry has a matching CLSID, stop enumerating.
  686.     if( pExtra->guidCLSID == rguidCLSID )
  687.     {
  688.         pExtra->fFoundCLSID = TRUE;
  689.         fRetVal = FALSE;
  690.     }
  691.  
  692.     return fRetVal;
  693. }
  694.  
  695. #pragma warning(default:4100)   // "unreferenced formal parameter" warning
  696.  
  697. //----------------------------------------------------------------
  698. // MyRegisterUnregister()
  699. //----------------------------------------------------------------
  700. HRESULT
  701. MyRegisterUnregister(
  702.     BOOL fRegister )
  703. {
  704.     ULONG       iCRIEntry;
  705.     BOOL        fRes;
  706.     HRESULT     hr;
  707.     HRESULT     hrCoInit;
  708.     ULONG       cCRIEntries;
  709.     ExtraEnumerationData    extra;
  710.  
  711.     if ( 0 == GetModuleFileName( g_hModuleMine, g_szFileName, BUFSIZE ) )
  712.         return E_UNEXPECTED;
  713.  
  714.     LoadCRIData();
  715.     if ( g_hCRIData == NULL )
  716.         return E_UNEXPECTED;
  717.  
  718.     cCRIEntries = CRIGetEntryCount(g_hCRIData);
  719.     extra.pModuleManager = NULL;
  720.     extra.ppunkClassObjects = NULL;
  721.  
  722.     // initialize COM and create an instance of StdJavaComModuleManager.  we
  723.     //  don't want to call InitializeDll() here and use the global
  724.     //  StdJavaComModuleManager.  that may cause us to fault in our
  725.     //  DLL_PROCESS_DETACH code, when we try to use a bogus
  726.     //  StdJavaComModuleManager (bogus because msjava.dll may be unloaded
  727.     //  before us).
  728.     hrCoInit = CoInitialize( NULL );
  729.     if( FAILED( hrCoInit ) &&
  730.             (hrCoInit != RPC_E_CHANGED_MODE) ) {
  731.         hr = hrCoInit;
  732.         goto Error;
  733.     }
  734.  
  735.     hr = CoCreateInstance( CLSID_StdJavaComModuleManager, NULL,
  736.                             CLSCTX_INPROC_SERVER, IID_IJavaComModuleManager,
  737.                             (LPVOID *)&(extra.pModuleManager) );
  738.     if( FAILED( hr ) ) {
  739.         goto Error;
  740.     }
  741.  
  742.     // when performing unregistration, we have a problem- we wish to call
  743.     //  the user's onCOMRegister() method after we have removed all registry
  744.     //  entries.  but, we actually ask the VM to call onCOMRegister() for us,
  745.     //  and the VM uses registry values to load the correct class.  to get
  746.     //  around this, we force the VM to load registry info before we remove it
  747.     //  by asking for class objects for each class we'll be unregistering.
  748.  
  749.     // allocate space for an array of class objects.
  750.     if (!fRegister) {
  751.         // we explicitly use HeapAlloc() to ensure that we don't use
  752.         //  the CRT libraries.
  753.         extra.ppunkClassObjects = (IUnknown**) HeapAlloc(GetProcessHeap(), 0,
  754.             sizeof(IUnknown*) * cCRIEntries);
  755.         if (!extra.ppunkClassObjects) {
  756.             hr = E_OUTOFMEMORY;
  757.             goto Error;
  758.         }
  759.  
  760.         for (iCRIEntry = 0; iCRIEntry < cCRIEntries; iCRIEntry++ ) {
  761.             extra.ppunkClassObjects[iCRIEntry] = NULL;
  762.         }
  763.     }
  764.  
  765.     // enumerate over the CRI data, registering or unregistering as necessary.
  766.     //  if unregistering, this will also fill the ppunkClassObjects field of
  767.     //  the extra data.
  768.     extra.fRegister = fRegister;
  769.     fRes = CRIEnumEntries(g_hCRIData, RegistrationCallback, &extra);
  770.  
  771.     if ( !fRes ) {
  772.         hr = E_UNEXPECTED;
  773.         goto Error;
  774.     }
  775.  
  776.     // register type libraries.
  777.     g_fTypeLibError = FALSE;
  778.     EnumResourceNames(g_hModuleMine, "TYPELIB", MyRegisterTypeLib,
  779.         (LONG_PTR)fRegister);
  780.  
  781.     if ( g_fTypeLibError ) {
  782.         hr = E_UNEXPECTED;
  783.         goto Error;
  784.     }
  785.  
  786.     // Invoke the user registration handler for any classes that have one.
  787.     extra.hr = S_OK;
  788.     fRes = CRIEnumEntries(g_hCRIData, UserRegHandlerCallback, &extra);
  789.     hr = extra.hr;
  790.  
  791.     if (FAILED(hr))
  792.         goto Error;
  793.  
  794.     hr = S_OK;
  795.  
  796. Error:
  797.     // clean up the class object punks.
  798.     if (extra.ppunkClassObjects) {
  799.         for (iCRIEntry = 0; iCRIEntry < cCRIEntries; iCRIEntry++ ) {
  800.             if (extra.ppunkClassObjects[iCRIEntry]) {
  801.                 extra.ppunkClassObjects[iCRIEntry]->Release();
  802.             }
  803.         }
  804.         HeapFree(GetProcessHeap(), 0, extra.ppunkClassObjects);
  805.     }
  806.  
  807.     if( extra.pModuleManager != NULL ) {
  808.         extra.pModuleManager->Release();
  809.     }
  810.  
  811.     if( SUCCEEDED( hrCoInit ) ) {
  812.         CoUninitialize();
  813.     }
  814.  
  815.     return hr;
  816. }
  817.  
  818. /************************** class MyClassFactory *************************/
  819. HRESULT
  820. MyClassFactory::QueryInterface(
  821.     REFIID  iid,
  822.     LPVOID  *ppv )
  823. {
  824.     if( ppv == NULL )
  825.         return E_INVALIDARG;
  826.  
  827.     if( iid != IID_IUnknown &&
  828.         iid != IID_IClassFactory ) {
  829.  
  830.         *ppv = NULL;
  831.         return E_NOINTERFACE;
  832.     }
  833.  
  834.     *ppv = this;
  835.     AddRef();
  836.     return S_OK;
  837. }
  838.  
  839. ULONG
  840. MyClassFactory::AddRef( void )
  841. {
  842.     return ++g_dwUseCount;
  843. }
  844.  
  845. ULONG
  846. MyClassFactory::Release( void )
  847. {
  848.     return --g_dwUseCount;
  849. }
  850.  
  851. HRESULT
  852. MyClassFactory::CreateInstance(
  853.     IUnknown    *pUnkOuter,
  854.     REFIID      iid,
  855.     LPVOID      *ppv )
  856. {
  857.     UNREFERENCED_PARAMETER( pUnkOuter );
  858.     UNREFERENCED_PARAMETER( iid );
  859.  
  860.     if( ppv == NULL )
  861.         return E_INVALIDARG;
  862.  
  863.     *ppv = NULL;
  864.     return E_UNEXPECTED;
  865. }
  866.  
  867. HRESULT
  868. MyClassFactory::LockServer(
  869.     BOOL fLock )
  870. {
  871.     if( fLock )
  872.         g_dwLockCount++;
  873.     else
  874.         g_dwLockCount--;
  875.  
  876.     return S_OK;
  877. }
  878.  
  879. /****************************** Public Functions *****************************/
  880.  
  881. //----------------------------------------------------------------
  882. // DllMain() - DLL entry point
  883. //----------------------------------------------------------------
  884. BOOL
  885. WINAPI
  886. DllMain(
  887.     HINSTANCE   hModule,
  888.     ULONG       ulReasonForCall,
  889.     LPVOID      lpReserved )
  890. {
  891.     UNREFERENCED_PARAMETER( lpReserved );
  892.  
  893.     switch ( ulReasonForCall ) {
  894.  
  895.         case DLL_PROCESS_ATTACH:
  896.             g_hModuleMine = hModule;
  897.             InitializeCriticalSection(&g_CriticalSection);
  898.             DisableThreadLibraryCalls(hModule);
  899.             return TRUE;
  900.  
  901.         case DLL_PROCESS_DETACH:
  902.             DeleteCriticalSection( &g_CriticalSection );
  903.             if ( g_hCRIData != NULL ) {
  904.                 CRICloseData(g_hCRIData);
  905.                 g_hCRIData = NULL;
  906.             }
  907.  
  908.             if (g_pModuleManager) {
  909.                 // Notify the module manager that we're unloading.
  910.                 g_pModuleManager->OnModuleUnload(g_hModuleMine);
  911.  
  912.                 g_pModuleManager->Release();
  913.                 g_pModuleManager = NULL;
  914.             }
  915.  
  916.             return TRUE;
  917.  
  918.         default:
  919.             return TRUE;
  920.     }
  921. }
  922.  
  923. // Don't link in CRT startup code.
  924. extern "C"
  925. BOOL
  926. WINAPI
  927. _DllMainCRTStartup(
  928.     HINSTANCE   hDllHandle,
  929.     DWORD       dwReason,
  930.     LPVOID      lpReserved )
  931. {
  932.     return DllMain(hDllHandle, dwReason, lpReserved);
  933. }
  934.  
  935.  
  936. //----------------------------------------------------------------
  937. // DllCanUnloadNow()
  938. //----------------------------------------------------------------
  939. extern "C"
  940. HRESULT
  941. __stdcall
  942. DllCanUnloadNow( void )
  943. {
  944.     HRESULT hr;
  945.  
  946.     if ( !g_fInitialized ) {
  947.         hr = InitializeDll();
  948.         if (FAILED(hr))
  949.             return hr;
  950.     }
  951.  
  952.     if ( g_dwUseCount > 0 )
  953.         return S_FALSE;
  954.  
  955.     if ( g_dwLockCount > 0 )
  956.         return S_FALSE;
  957.  
  958.     if (g_pModuleManager)
  959.         return g_pModuleManager->CanUnloadNow(g_hModuleMine);
  960.  
  961.     return S_OK;
  962. }
  963.  
  964. //----------------------------------------------------------------
  965. // DllGetClassObject()
  966. //----------------------------------------------------------------
  967. extern "C"
  968. HRESULT
  969. __stdcall
  970. DllGetClassObject(
  971.     REFCLSID    rclsid,
  972.     REFIID      riid,
  973.     LPVOID      *ppv )
  974. {
  975.     HRESULT hr;
  976.     FindCLSIDCallbackExtra  extra;
  977.  
  978.     if ( !g_fInitialized ) {
  979.         hr = InitializeDll();
  980.         if (FAILED(hr))
  981.             return hr;
  982.     }
  983.  
  984.     hr = g_pModuleManager->GetClassObject(rclsid, g_hModuleMine,
  985.         CLSCTX_INPROC_SERVER, riid, ppv);
  986.  
  987.     if ( hr != CLASS_E_CLASSNOTAVAILABLE )
  988.         return hr;
  989.  
  990.     // here we have a kludge. Some administrative tools attempt to get a class
  991.     //  object before the registration code has run, just to see if the DLL
  992.     //  implements a specific class.  When called before we have
  993.     //  self-registered, JAVA returns CLASS_E_CLASSNOTAVAILABLE. If the class
  994.     //  is one that we would have registered, we return a reference to our own
  995.     //  class object here.
  996.  
  997.     LoadCRIData();
  998.     if ( g_hCRIData == NULL )
  999.         return CLASS_E_CLASSNOTAVAILABLE;   // we don't have any info to look at
  1000.  
  1001.     // enumerate the CRI data, looking for an entry whose CLSID matches
  1002.     //  that requested.  the fFoundCLSID field of the extra data will be
  1003.     //  set to TRUE if a matching entry is found.
  1004.     extra.guidCLSID = rclsid;
  1005.     extra.fFoundCLSID = FALSE;
  1006.     CRIEnumEntries(g_hCRIData, FindCLSIDCallback, &extra);
  1007.  
  1008.     if ( extra.fFoundCLSID ) {
  1009.         return g_pMyClassFactory->QueryInterface( riid, ppv );
  1010.     }
  1011.  
  1012.     return CLASS_E_CLASSNOTAVAILABLE;       // class is not one that we will register
  1013. }
  1014.  
  1015. //----------------------------------------------------------------
  1016. // DllRegisterServer()
  1017. //----------------------------------------------------------------
  1018. extern "C"
  1019. HRESULT
  1020. __stdcall
  1021. DllRegisterServer( void )
  1022. {
  1023.     return MyRegisterUnregister( TRUE );
  1024. }
  1025.  
  1026. //----------------------------------------------------------------
  1027. // DllUnregisterServer()
  1028. //----------------------------------------------------------------
  1029. extern "C"
  1030. HRESULT
  1031. __stdcall
  1032. DllUnregisterServer( void )
  1033. {
  1034.     return MyRegisterUnregister( FALSE );
  1035. }
  1036.