home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / plugins / ImAlive / npmac.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  17.5 KB  |  613 lines

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. //
  20. // npmac.cpp
  21. //
  22.  
  23. #include <Processes.h>
  24. #include <Gestalt.h>
  25. #include <FragLoad.h>
  26. #include <Timer.h>
  27. #include <Resources.h>
  28. #include <ToolUtils.h>
  29.  
  30. #define XP_MAC 1
  31.  
  32. //
  33. // A4Stuff.h contains the definition of EnterCodeResource and 
  34. // EnterCodeResource, used for setting up the code resource╒s
  35. // globals for 68K (analagous to the function SetCurrentA5
  36. // defined by the toolbox).
  37. //
  38. #include <A4Stuff.h>
  39.  
  40.  
  41. #include "npapi.h"
  42.  
  43. //
  44. // The Mixed Mode procInfos defined in npupp.h assume Think C-
  45. // style calling conventions.  These conventions are used by
  46. // Metrowerks with the exception of pointer return types, which
  47. // in Metrowerks 68K are returned in A0, instead of the standard
  48. // D0. Thus, since NPN_MemAlloc and NPN_UserAgent return pointers,
  49. // Mixed Mode will return the values to a 68K plugin in D0, but 
  50. // a 68K plugin compiled by Metrowerks will expect the result in
  51. // A0.  The following pragma forces Metrowerks to use D0 instead.
  52. //
  53. #ifdef __MWERKS__
  54. #ifndef powerc
  55. #pragma pointers_in_D0
  56. #endif
  57. #endif
  58.  
  59. #include "npupp.h"
  60.  
  61. #ifdef __MWERKS__
  62. #ifndef powerc
  63. #pragma pointers_in_A0
  64. #endif
  65. #endif
  66.  
  67.  
  68. //
  69. // Define PLUGIN_TRACE to 1 to have the wrapper functions emit
  70. // DebugStr messages whenever they are called.
  71. //
  72. #define PLUGIN_TRACE 0
  73.  
  74. #if PLUGIN_TRACE
  75. #define PLUGINDEBUGSTR(msg)        ::DebugStr(msg)
  76. #else
  77. #define PLUGINDEBUGSTR
  78. #endif
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  86. //
  87. // Globals
  88. //
  89. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  90.  
  91. QDGlobals*        gQDPtr;                // Pointer to Netscape╒s QuickDraw globals
  92. short            gResFile;            // Refnum of the plugin╒s resource file
  93. NPNetscapeFuncs    gNetscapeFuncs;        // Function table for procs in Netscape called by plugin
  94.  
  95.  
  96. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  97. //
  98. // Wrapper functions for all calls from the plugin to Netscape.
  99. // These functions let the plugin developer just call the APIs
  100. // as documented and defined in npapi.h, without needing to know
  101. // about the function table and call macros in npupp.h.
  102. //
  103. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  104.  
  105.  
  106. void NPN_Version(int* plugin_major, int* plugin_minor, int* netscape_major, int* netscape_minor)
  107. {
  108.     *plugin_major = NP_VERSION_MAJOR;
  109.     *plugin_minor = NP_VERSION_MINOR;
  110.     *netscape_major = gNetscapeFuncs.version >> 8;        // Major version is in high byte
  111.     *netscape_minor = gNetscapeFuncs.version & 0xFF;    // Minor version is in low byte
  112. }
  113.  
  114. NPError NPN_GetURLNotify(NPP instance, const char* url, const char* window, void* notifyData)
  115. {
  116.     int navMinorVers = gNetscapeFuncs.version & 0xFF;
  117.     NPError err;
  118.     
  119.     if( navMinorVers >= NPVERS_HAS_NOTIFICATION )
  120.     {
  121.         err = CallNPN_GetURLNotifyProc(gNetscapeFuncs.geturlnotify, instance, url, window, notifyData);
  122.     }
  123.     else
  124.     {
  125.         err = NPERR_INCOMPATIBLE_VERSION_ERROR;
  126.     }
  127.     return err;
  128. }
  129.  
  130. NPError NPN_GetURL(NPP instance, const char* url, const char* window)
  131. {
  132.     return CallNPN_GetURLProc(gNetscapeFuncs.geturl, instance, url, window);
  133. }
  134.  
  135. NPError NPN_PostURLNotify(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData)
  136. {
  137.     int navMinorVers = gNetscapeFuncs.version & 0xFF;
  138.     NPError err;
  139.     
  140.     if( navMinorVers >= NPVERS_HAS_NOTIFICATION )
  141.     {
  142.         err = CallNPN_PostURLNotifyProc(gNetscapeFuncs.posturlnotify, instance, url, 
  143.                                                         window, len, buf, file, notifyData);
  144.     }
  145.     else
  146.     {
  147.         err = NPERR_INCOMPATIBLE_VERSION_ERROR;
  148.     }
  149.     return err;
  150. }
  151.  
  152. NPError NPN_PostURL(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file)
  153. {
  154.     return CallNPN_PostURLProc(gNetscapeFuncs.posturl, instance, url, window, len, buf, file);
  155. }
  156.  
  157. NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
  158. {
  159.     return CallNPN_RequestReadProc(gNetscapeFuncs.requestread, stream, rangeList);
  160. }
  161.  
  162. NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* window, NPStream** stream)
  163. {
  164.     int navMinorVers = gNetscapeFuncs.version & 0xFF;
  165.     NPError err;
  166.     
  167.     if( navMinorVers >= NPVERS_HAS_STREAMOUTPUT )
  168.     {
  169.         err = CallNPN_NewStreamProc(gNetscapeFuncs.newstream, instance, type, window, stream);
  170.     }
  171.     else
  172.     {
  173.         err = NPERR_INCOMPATIBLE_VERSION_ERROR;
  174.     }
  175.     return err;
  176. }
  177.  
  178. int32 NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer)
  179. {
  180.     int navMinorVers = gNetscapeFuncs.version & 0xFF;
  181.     NPError err;
  182.     
  183.     if( navMinorVers >= NPVERS_HAS_STREAMOUTPUT )
  184.     {
  185.         err = CallNPN_WriteProc(gNetscapeFuncs.write, instance, stream, len, buffer);
  186.     }
  187.     else
  188.     {
  189.         err = NPERR_INCOMPATIBLE_VERSION_ERROR;
  190.     }
  191.     return err;
  192. }
  193.  
  194. NPError    NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason)
  195. {
  196.     int navMinorVers = gNetscapeFuncs.version & 0xFF;
  197.     NPError err;
  198.     
  199.     if( navMinorVers >= NPVERS_HAS_STREAMOUTPUT )
  200.     {
  201.         err = CallNPN_DestroyStreamProc(gNetscapeFuncs.destroystream, instance, stream, reason);
  202.     }
  203.     else
  204.     {
  205.         err = NPERR_INCOMPATIBLE_VERSION_ERROR;
  206.     }
  207.     return err;
  208. }
  209.  
  210. void NPN_Status(NPP instance, const char* message)
  211. {
  212.     CallNPN_StatusProc(gNetscapeFuncs.status, instance, message);
  213. }
  214.  
  215. const char* NPN_UserAgent(NPP instance)
  216. {
  217.     return CallNPN_UserAgentProc(gNetscapeFuncs.uagent, instance);
  218. }
  219.  
  220. void* NPN_MemAlloc(uint32 size)
  221. {
  222.     return CallNPN_MemAllocProc(gNetscapeFuncs.memalloc, size);
  223. }
  224.  
  225. void NPN_MemFree(void* ptr)
  226. {
  227.     CallNPN_MemFreeProc(gNetscapeFuncs.memfree, ptr);
  228. }
  229.  
  230. uint32 NPN_MemFlush(uint32 size)
  231. {
  232.     return CallNPN_MemFlushProc(gNetscapeFuncs.memflush, size);
  233. }
  234.  
  235. void NPN_ReloadPlugins(NPBool reloadPages)
  236. {
  237.     CallNPN_ReloadPluginsProc(gNetscapeFuncs.reloadplugins, reloadPages);
  238. }
  239.  
  240.  
  241. JRIEnv* NPN_GetJavaEnv(void)
  242. {
  243.     return CallNPN_GetJavaEnvProc( gNetscapeFuncs.getJavaEnv );
  244. }
  245.  
  246. jref  NPN_GetJavaPeer(NPP instance)
  247. {
  248.     return CallNPN_GetJavaPeerProc( gNetscapeFuncs.getJavaPeer, instance );
  249. }
  250.  
  251.  
  252.  
  253. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  254. //
  255. // Wrapper functions for all calls from Netscape to the plugin.
  256. // These functions let the plugin developer just create the APIs
  257. // as documented and defined in npapi.h, without needing to 
  258. // install those functions in the function table or worry about
  259. // setting up globals for 68K plugins.
  260. //
  261. //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  262.  
  263. NPError     Private_Initialize(void);
  264. void         Private_Shutdown(void);
  265. NPError        Private_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved);
  266. NPError     Private_Destroy(NPP instance, NPSavedData** save);
  267. NPError        Private_SetWindow(NPP instance, NPWindow* window);
  268. NPError        Private_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype);
  269. NPError        Private_DestroyStream(NPP instance, NPStream* stream, NPError reason);
  270. int32        Private_WriteReady(NPP instance, NPStream* stream);
  271. int32        Private_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer);
  272. void        Private_StreamAsFile(NPP instance, NPStream* stream, const char* fname);
  273. void        Private_Print(NPP instance, NPPrint* platformPrint);
  274. int16         Private_HandleEvent(NPP instance, void* event);
  275. void        Private_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData);
  276. jref        Private_GetJavaClass(void);
  277.  
  278.  
  279. NPError Private_Initialize(void)
  280. {
  281.     NPError err;
  282.     EnterCodeResource();
  283.     PLUGINDEBUGSTR("\pInitialize;g;");
  284.     err = NPP_Initialize();
  285.     ExitCodeResource();
  286.     return err;
  287. }
  288.  
  289. void Private_Shutdown(void)
  290. {
  291.     EnterCodeResource();
  292.     PLUGINDEBUGSTR("\pShutdown;g;");
  293.     NPP_Shutdown();
  294.     ExitCodeResource();
  295. }
  296.  
  297.  
  298. NPError    Private_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved)
  299. {
  300.     EnterCodeResource();
  301.     NPError ret = NPP_New(pluginType, instance, mode, argc, argn, argv, saved);
  302.     PLUGINDEBUGSTR("\pNew;g;");
  303.     ExitCodeResource();
  304.     return ret;    
  305. }
  306.  
  307. NPError Private_Destroy(NPP instance, NPSavedData** save)
  308. {
  309.     NPError err;
  310.     EnterCodeResource();
  311.     PLUGINDEBUGSTR("\pDestroy;g;");
  312.     err = NPP_Destroy(instance, save);
  313.     ExitCodeResource();
  314.     return err;
  315. }
  316.  
  317. NPError Private_SetWindow(NPP instance, NPWindow* window)
  318. {
  319.     NPError err;
  320.     EnterCodeResource();
  321.     PLUGINDEBUGSTR("\pSetWindow;g;");
  322.     err = NPP_SetWindow(instance, window);
  323.     ExitCodeResource();
  324.     return err;
  325. }
  326.  
  327. NPError Private_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
  328. {
  329.     NPError err;
  330.     EnterCodeResource();
  331.     PLUGINDEBUGSTR("\pNewStream;g;");
  332.     err = NPP_NewStream(instance, type, stream, seekable, stype);
  333.     ExitCodeResource();
  334.     return err;
  335. }
  336.  
  337. int32 Private_WriteReady(NPP instance, NPStream* stream)
  338. {
  339.     int32 result;
  340.     EnterCodeResource();
  341.     PLUGINDEBUGSTR("\pWriteReady;g;");
  342.     result = NPP_WriteReady(instance, stream);
  343.     ExitCodeResource();
  344.     return result;
  345. }
  346.  
  347. int32 Private_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer)
  348. {
  349.     int32 result;
  350.     EnterCodeResource();
  351.     PLUGINDEBUGSTR("\pWrite;g;");
  352.     result = NPP_Write(instance, stream, offset, len, buffer);
  353.     ExitCodeResource();
  354.     return result;
  355. }
  356.  
  357. void Private_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
  358. {
  359.     EnterCodeResource();
  360.     PLUGINDEBUGSTR("\pStreamAsFile;g;");
  361.     NPP_StreamAsFile(instance, stream, fname);
  362.     ExitCodeResource();
  363. }
  364.  
  365.  
  366. NPError Private_DestroyStream(NPP instance, NPStream* stream, NPError reason)
  367. {
  368.     NPError err;
  369.     EnterCodeResource();
  370.     PLUGINDEBUGSTR("\pDestroyStream;g;");
  371.     err = NPP_DestroyStream(instance, stream, reason);
  372.     ExitCodeResource();
  373.     return err;
  374. }
  375.  
  376. int16 Private_HandleEvent(NPP instance, void* event)
  377. {
  378.     int16 result;
  379.     EnterCodeResource();
  380.     PLUGINDEBUGSTR("\pHandleEvent;g;");
  381.     result = NPP_HandleEvent(instance, event);
  382.     ExitCodeResource();
  383.     return result;
  384. }
  385.  
  386. void Private_Print(NPP instance, NPPrint* platformPrint)
  387. {
  388.     EnterCodeResource();
  389.     PLUGINDEBUGSTR("\pPrint;g;");
  390.     NPP_Print(instance, platformPrint);
  391.     ExitCodeResource();
  392. }
  393.  
  394. void Private_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
  395. {
  396.     EnterCodeResource();
  397.     PLUGINDEBUGSTR("\pURLNotify;g;");
  398.     NPP_URLNotify(instance, url, reason, notifyData);
  399.     ExitCodeResource();
  400. }
  401.  
  402.  
  403. jref Private_GetJavaClass(void)
  404. {
  405.     EnterCodeResource();
  406.     PLUGINDEBUGSTR("\pGetJavaClass;g;");
  407.  
  408.     jref clazz = NPP_GetJavaClass();
  409.     ExitCodeResource();
  410.     if (clazz)
  411.     {
  412.         JRIEnv* env = NPN_GetJavaEnv();
  413.         return JRI_NewGlobalRef(env, clazz);
  414.     }
  415.     return NULL;
  416. }
  417.  
  418.  
  419. void SetUpQD(void);
  420. void SetUpQD(void)
  421. {
  422.     ProcessSerialNumber PSN;
  423.     FSSpec                myFSSpec;
  424.     Str63                name;
  425.     ProcessInfoRec        infoRec;
  426.     OSErr                result = noErr;
  427.     ConnectionID         connID;
  428.     Str255                 errName;
  429.     
  430.     //
  431.     // Memorize the plugin╒s resource file 
  432.     // refnum for later use.
  433.     //
  434.     gResFile = CurResFile();
  435.     
  436.     //
  437.     // Ask the system if CFM is available.
  438.     //
  439.     long response;
  440.     OSErr err = Gestalt(gestaltCFMAttr, &response);
  441.     Boolean hasCFM = BitTst(&response, 31-gestaltCFMPresent);
  442.             
  443.     if (hasCFM)
  444.     {
  445.         //
  446.         // GetProcessInformation takes a process serial number and 
  447.         // will give us back the name and FSSpec of the application.
  448.         // See the Process Manager in IM.
  449.         //
  450.         infoRec.processInfoLength = sizeof(ProcessInfoRec);
  451.         infoRec.processName = name;
  452.         infoRec.processAppSpec = &myFSSpec;
  453.         
  454.         PSN.highLongOfPSN = 0;
  455.         PSN.lowLongOfPSN = kCurrentProcess;
  456.         
  457.         result = GetProcessInformation(&PSN, &infoRec);
  458.         if (result != noErr)
  459.             PLUGINDEBUGSTR("\pFailed in GetProcessInformation");
  460.         }
  461.     else
  462.         //
  463.         // If no CFM installed, assume it must be a 68K app.
  464.         //
  465.         result = -1;        
  466.         
  467.     if (result == noErr)
  468.     {
  469.         //
  470.         // Now that we know the app name and FSSpec, we can call GetDiskFragment
  471.         // to get a connID to use in a subsequent call to FindSymbol (it will also
  472.         // return the address of ╥main╙ in app, which we ignore).  If GetDiskFragment 
  473.         // returns an error, we assume the app must be 68K.
  474.         //
  475.         Ptr mainAddr;     
  476.         result =  GetDiskFragment(infoRec.processAppSpec, 0L, 0L, infoRec.processName,
  477.                                   kLoadLib, &connID, (Ptr*)&mainAddr, errName);
  478.     }
  479.  
  480.     if (result == noErr) 
  481.     {
  482.         //
  483.         // The app is a PPC code fragment, so call FindSymbol
  484.         // to get the exported ╥qd╙ symbol so we can access its
  485.         // QuickDraw globals.
  486.         //
  487.         SymClass symClass;
  488.         result = FindSymbol(connID, "\pqd", (Ptr*)&gQDPtr, &symClass);
  489.         if (result != noErr)
  490.             PLUGINDEBUGSTR("\pFailed in FindSymbol qd");
  491.     }
  492.     else
  493.     {
  494.         //
  495.         // The app is 68K, so use its A5 to compute the address
  496.         // of its QuickDraw globals.
  497.         //
  498.         gQDPtr = (QDGlobals*)(*((long*)SetCurrentA5()) - (sizeof(QDGlobals) - sizeof(GrafPtr)));
  499.     }
  500.  
  501. }
  502.  
  503.  
  504.  
  505. NPError main(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs, NPP_ShutdownUPP* unloadUpp);
  506.  
  507. #if GENERATINGCFM
  508. RoutineDescriptor mainRD = BUILD_ROUTINE_DESCRIPTOR(uppNPP_MainEntryProcInfo, main);
  509. #endif
  510.  
  511.  
  512. NPError main(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs, NPP_ShutdownUPP* unloadUpp)
  513. {
  514.     EnterCodeResource();
  515.     PLUGINDEBUGSTR("\pmain");
  516.  
  517.     NPError err = NPERR_NO_ERROR;
  518.     
  519.     //
  520.     // Ensure that everything Netscape passed us is valid!
  521.     //
  522.     if ((nsTable == NULL) || (pluginFuncs == NULL) || (unloadUpp == NULL))
  523.         err = NPERR_INVALID_FUNCTABLE_ERROR;
  524.     
  525.     //
  526.     // Check the ╥major╙ version passed in Netscape╒s function table.
  527.     // We won╒t load if the major version is newer than what we expect.
  528.     // Also check that the function tables passed in are big enough for
  529.     // all the functions we need (they could be bigger, if Netscape added
  530.     // new APIs, but that╒s OK with us -- we╒ll just ignore them).
  531.     //
  532.     if (err == NPERR_NO_ERROR)
  533.     {
  534.         if ((nsTable->version >> 8) > NP_VERSION_MAJOR)        // Major version is in high byte
  535.             err = NPERR_INCOMPATIBLE_VERSION_ERROR;
  536. //        if (nsTable->size < sizeof(NPNetscapeFuncs))
  537. //            err = NPERR_INVALID_FUNCTABLE_ERROR;
  538. //        if (pluginFuncs->size < sizeof(NPPluginFuncs))        
  539. //            err = NPERR_INVALID_FUNCTABLE_ERROR;
  540.     }
  541.         
  542.     
  543.     if (err == NPERR_NO_ERROR)
  544.     {
  545.         //
  546.         // Copy all the fields of Netscape╒s function table into our
  547.         // copy so we can call back into Netscape later.  Note that
  548.         // we need to copy the fields one by one, rather than assigning
  549.         // the whole structure, because the Netscape function table
  550.         // could actually be bigger than what we expect.
  551.         //
  552.         
  553.         int navMinorVers = nsTable->version & 0xFF;
  554.  
  555.         gNetscapeFuncs.version = nsTable->version;
  556.         gNetscapeFuncs.size = nsTable->size;
  557.         gNetscapeFuncs.posturl = nsTable->posturl;
  558.         gNetscapeFuncs.geturl = nsTable->geturl;
  559.         gNetscapeFuncs.requestread = nsTable->requestread;
  560.         gNetscapeFuncs.newstream = nsTable->newstream;
  561.         gNetscapeFuncs.write = nsTable->write;
  562.         gNetscapeFuncs.destroystream = nsTable->destroystream;
  563.         gNetscapeFuncs.status = nsTable->status;
  564.         gNetscapeFuncs.uagent = nsTable->uagent;
  565.         gNetscapeFuncs.memalloc = nsTable->memalloc;
  566.         gNetscapeFuncs.memfree = nsTable->memfree;
  567.         gNetscapeFuncs.memflush = nsTable->memflush;
  568.         gNetscapeFuncs.reloadplugins = nsTable->reloadplugins;
  569.         if( navMinorVers >= NPVERS_HAS_LIVECONNECT )
  570.         {
  571.             gNetscapeFuncs.getJavaEnv = nsTable->getJavaEnv;
  572.             gNetscapeFuncs.getJavaPeer = nsTable->getJavaPeer;
  573.         }
  574.         if( navMinorVers >= NPVERS_HAS_NOTIFICATION )
  575.         {    
  576.             gNetscapeFuncs.geturlnotify = nsTable->geturlnotify;
  577.             gNetscapeFuncs.posturlnotify = nsTable->posturlnotify;
  578.         }
  579.         
  580.         //
  581.         // Set up the plugin function table that Netscape will use to
  582.         // call us.  Netscape needs to know about our version and size
  583.         // and have a UniversalProcPointer for every function we implement.
  584.         //
  585.         pluginFuncs->version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
  586.         pluginFuncs->size = sizeof(NPPluginFuncs);
  587.         pluginFuncs->newp = NewNPP_NewProc(Private_New);
  588.         pluginFuncs->destroy = NewNPP_DestroyProc(Private_Destroy);
  589.         pluginFuncs->setwindow = NewNPP_SetWindowProc(Private_SetWindow);
  590.         pluginFuncs->newstream = NewNPP_NewStreamProc(Private_NewStream);
  591.         pluginFuncs->destroystream = NewNPP_DestroyStreamProc(Private_DestroyStream);
  592.         pluginFuncs->asfile = NewNPP_StreamAsFileProc(Private_StreamAsFile);
  593.         pluginFuncs->writeready = NewNPP_WriteReadyProc(Private_WriteReady);
  594.         pluginFuncs->write = NewNPP_WriteProc(Private_Write);
  595.         pluginFuncs->print = NewNPP_PrintProc(Private_Print);
  596.         pluginFuncs->event = NewNPP_HandleEventProc(Private_HandleEvent);    
  597.         if( navMinorVers >= NPVERS_HAS_NOTIFICATION )
  598.         {    
  599.             pluginFuncs->urlnotify = NewNPP_URLNotifyProc(Private_URLNotify);            
  600.         }
  601.         if( navMinorVers >= NPVERS_HAS_LIVECONNECT )
  602.         {
  603.             pluginFuncs->javaClass    = (JRIGlobalRef) Private_GetJavaClass();
  604.         }
  605.         *unloadUpp = NewNPP_ShutdownProc(Private_Shutdown);
  606.         SetUpQD();
  607.         err = Private_Initialize();
  608.     }
  609.     
  610.     ExitCodeResource();
  611.     return err;
  612. }
  613.