Bladeren bron

HPCC-16931 Avoid loading dlls when extracting resources in esp

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 8 jaren geleden
bovenliggende
commit
aec724772b

+ 13 - 1
common/dllserver/dllserver.cpp

@@ -493,6 +493,7 @@ public:
     virtual void getLocalLibraryName(const char * name, StringBuffer & libraryName);
     virtual DllLocationType isAvailable(const char * name);
     virtual ILoadedDllEntry * loadDll(const char * name, DllLocationType location);
+    virtual ILoadedDllEntry * loadDllResources(const char * name, DllLocationType location);
     virtual void removeDll(const char * name, bool removeDlls, bool removeDirectory);
     virtual void registerDll(const char * name, const char * kind, const char * dllPath);
     virtual IDllEntry * createEntry(IPropertyTree *owner, IPropertyTree *entry);
@@ -503,6 +504,7 @@ protected:
     void doRegisterDll(const char * name, const char * kind, const char * dllPath, const char * libPath);
     IDllLocation * getBestMatch(const char * name);
     IDllLocation * getBestMatchEx(const char * name);
+    ILoadedDllEntry * doLoadDll(const char * name, DllLocationType location, bool resourcesOnly);
 
 protected:
     StringAttr rootDir;
@@ -723,6 +725,16 @@ DllLocationType DllServer::isAvailable(const char * name)
 
 ILoadedDllEntry * DllServer::loadDll(const char * name, DllLocationType type)
 {
+    return doLoadDll(name, type, false);
+}
+
+ILoadedDllEntry * DllServer::loadDllResources(const char * name, DllLocationType type)
+{
+    return doLoadDll(name, type, true);
+}
+
+ILoadedDllEntry * DllServer::doLoadDll(const char * name, DllLocationType type, bool resourcesOnly)
+{
 #ifdef _WIN32
     if (type < DllLocationDomain)
         type = DllLocationDomain;
@@ -737,7 +749,7 @@ ILoadedDllEntry * DllServer::loadDll(const char * name, DllLocationType type)
     StringBuffer x;
     rfile.getPath(x);
     LOG(MCdebugInfo, unknownJob, "Loading dll (%s) from location %s", name, x.str());
-    return createDllEntry(x.str(), false, NULL);
+    return createDllEntry(x.str(), false, NULL, resourcesOnly);
 }
 
 void DllServer::removeDll(const char * name, bool removeDlls, bool removeDirectory)

+ 1 - 0
common/dllserver/dllserver.hpp

@@ -77,6 +77,7 @@ interface IDllServer : extends IInterface
     virtual void getLocalLibraryName(const char * name, StringBuffer & libraryName) = 0;
     virtual DllLocationType isAvailable(const char * name) = 0;
     virtual ILoadedDllEntry * loadDll(const char * name, DllLocationType location) = 0;
+    virtual ILoadedDllEntry * loadDllResources(const char * name, DllLocationType location) = 0;
     virtual void removeDll(const char * name, bool removeDlls, bool removeDirectory) = 0;
     virtual void registerDll(const char * name, const char * kind, const char * dllPath) = 0;
     virtual IDllEntry * createEntry(IPropertyTree *owner, IPropertyTree *entry) = 0;

+ 225 - 165
common/dllserver/thorplugin.cpp

@@ -66,165 +66,7 @@ const char * SimplePluginCtx::ctxQueryProp(const char *propName) const
 
 //-------------------------------------------------------------------------------------------------------------------
 
-class HelperDll : implements ILoadedDllEntry, public CInterface
-{
-    SharedObject so;
-    StringAttr name;
-    Linked<const IFileIO> dllFile;
-    bool logLoad;
-public:
-    IMPLEMENT_IINTERFACE;
-    HelperDll(const char *_name, const IFileIO *dllFile);
-    ~HelperDll();
-
-//interface ILoadedDllEntry
-    virtual HINSTANCE getInstance() const;
-    virtual void * getEntry(const char * name) const;
-    virtual bool IsShared();
-    virtual const char * queryVersion() const;
-    virtual const char * queryName() const;
-    virtual const byte * getResource(unsigned id) const;
-    virtual bool getResource(size32_t & len, const void * & data, const char * type, unsigned id, bool trace) const;
-
-    bool load(bool isGlobal, bool raiseOnError);
-    bool loadCurrentExecutable();
-    virtual void logLoaded();
-    virtual bool checkVersion(const char *expected);
-};
-
-class PluginDll : public HelperDll
-{
-    ECLPluginDefinitionBlockEx pb;
-
-public:
-    PluginDll(const char *_name, const IFileIO *_dllFile) : HelperDll(_name, _dllFile) {}
-
-    bool init(IPluginContextEx * pluginCtx);
-
-    virtual bool checkVersion(const char *expected);
-    virtual void logLoaded();
-};
-
-HelperDll::HelperDll(const char *_name, const IFileIO *_dllFile) 
-: name(_name), dllFile(_dllFile)
-{
-    logLoad = false;
-}
-
-bool HelperDll::load(bool isGlobal, bool raiseOnError)
-{
-    if (!so.load(name, isGlobal, raiseOnError))
-        return false;
-    return true;
-}
-
-bool HelperDll::loadCurrentExecutable()
-{
-    if (!so.loadCurrentExecutable())
-        return false;
-    return true;
-}
-
-HelperDll::~HelperDll()
-{
-    if (logLoad)
-        DBGLOG("Unloading dll %s", name.get());
-}
-
-HINSTANCE HelperDll::getInstance() const
-{
-    return so.getInstanceHandle();
-}
-
-void * HelperDll::getEntry(const char * name) const
-{
-    return so.getEntry(name);
-}
-
-bool HelperDll::IsShared()
-{
-    return CInterface::IsShared();
-}
-
-const char * HelperDll::queryVersion() const
-{
-    return "";
-}
-
-void HelperDll::logLoaded()
-{
-    logLoad = true;
-    DBGLOG("Loaded DLL %s", name.get());
-}
-
-bool HelperDll::checkVersion(const char *expected)
-{
-    return true;
-}
-
-const char * HelperDll::queryName() const
-{
-    return name.get();
-}
-
-const byte * HelperDll::getResource(unsigned id) const
-{
-#ifdef _WIN32
-    HINSTANCE dllHandle = so.getInstanceHandle();
-    HRSRC hrsrc = FindResource(dllHandle, MAKEINTRESOURCE(id), "BIGSTRING");
-    if (hrsrc)
-        return (const byte *) LoadResource(dllHandle, hrsrc);
-    return NULL;
-#else
-    StringBuffer resourceName;
-    resourceName.appendf("BIGSTRING_%d_txt_start", id);
-    return (const byte *) getEntry(resourceName.str());
-#endif
-}
-
-const byte resourceHeaderVersion=1;
-const size32_t resourceHeaderLength = sizeof(byte) + sizeof(byte) + sizeof(bool) + sizeof(size32_t);
-
-
-bool HelperDll::getResource(size32_t & len, const void * & data, const char * type, unsigned id, bool trace) const
-{
-#ifdef _WIN32
-    HINSTANCE dllHandle = so.getInstanceHandle();
-    HRSRC hrsrc = FindResource(dllHandle, MAKEINTRESOURCE(id), type);
-    if (!hrsrc)
-        return false;
-    len = SizeofResource(dllHandle, hrsrc);
-    data = (const byte *) LoadResource(dllHandle, hrsrc);
-    return true;
-#else
-    StringBuffer symName;
-    symName.append(type).append("_").append(id).append("_txt_start");
-    data = (const void *) getEntry(symName.str());
-    if (!data)
-    {
-        if (trace)
-            printf("Failed to locate symbol %s\n", symName.str());
-        return false;
-    }
-    byte bom;
-    byte version;
-    bool compressed;
-
-    MemoryBuffer mb;
-    mb.setBuffer(resourceHeaderLength, const_cast<void *>(data));
-    mb.read(bom);
-    if (bom!=0x80)
-        return false;
-    mb.read(version);
-    if (version>resourceHeaderVersion)
-        return false;
-    mb.read(compressed).read(len);
-    len+=resourceHeaderLength;
-    return true;
-#endif
-}
-
-static bool getResourceFromMappedFile(const char * filename, const byte * start_addr, MemoryBuffer &data, const char * type, unsigned id)
+static bool getResourceFromMappedFile(const char * filename, const byte * start_addr, size32_t & lenData, const void * & data, const char * type, unsigned id)
 {
 #if defined(_WIN32)
     throwUnexpected();
@@ -239,8 +81,8 @@ static bool getResourceFromMappedFile(const char * filename, const byte * start_
     }
 
     unsigned long len = 0;
-    unsigned char *data2 = getsectiondata(mh, "__TEXT", sectname.str(), &len);
-    data.append(len, data2);
+    data = getsectiondata(mh, "__TEXT", sectname.str(), &len);
+    lenData = (size32_t)len;
     return true;
 #elif defined (__64BIT__)
     // The first bytes are the ELF header
@@ -275,7 +117,8 @@ static bool getResourceFromMappedFile(const char * filename, const byte * start_
         const char * sectionName = symbolTable + section.sh_name;
         if (streq(sectionName, sectname))
         {
-            data.append(section.sh_size, start_addr + section.sh_offset);
+            lenData = (size32_t)section.sh_size;
+            data = start_addr + section.sh_offset;
             return true;
         }
     }
@@ -315,7 +158,8 @@ static bool getResourceFromMappedFile(const char * filename, const byte * start_
         const char * sectionName = symbolTable + section.sh_name;
         if (streq(sectionName, sectname))
         {
-            data.append(section.sh_size, start_addr + section.sh_offset);
+            lenData = (size32_t)section.sh_size;
+            data = start_addr + section.sh_offset;
             return true;
         }
     }
@@ -325,6 +169,16 @@ static bool getResourceFromMappedFile(const char * filename, const byte * start_
 #endif
 }
 
+static bool getResourceFromMappedFile(const char * filename, const byte * start_addr, MemoryBuffer & result, const char * type, unsigned id)
+{
+    size32_t len = 0;
+    const void * data = nullptr;
+    bool ok = getResourceFromMappedFile(filename, start_addr, len, data, type, id);
+    if (ok)
+        result.append(len, data);
+    return ok;
+}
+
 extern bool getResourceFromFile(const char *filename, MemoryBuffer &data, const char * type, unsigned id)
 {
 #ifdef _WIN32
@@ -379,6 +233,207 @@ extern bool getResourceFromFile(const char *filename, MemoryBuffer &data, const
 
 //-------------------------------------------------------------------------------------------------------------------
 
+class HelperDll : implements ILoadedDllEntry, public CInterface
+{
+    SharedObject so;
+    StringAttr name;
+    Linked<const IFileIO> dllFile;
+    Owned<IMemoryMappedFile> mappedDll;
+    bool logLoad;
+public:
+    IMPLEMENT_IINTERFACE;
+    HelperDll(const char *_name, const IFileIO *dllFile);
+    ~HelperDll();
+
+//interface ILoadedDllEntry
+    virtual HINSTANCE getInstance() const;
+    virtual void * getEntry(const char * name) const;
+    virtual bool IsShared();
+    virtual const char * queryVersion() const;
+    virtual const char * queryName() const;
+    virtual const byte * getResource(unsigned id) const;
+    virtual bool getResource(size32_t & len, const void * & data, const char * type, unsigned id, bool trace) const;
+
+    bool load(bool isGlobal, bool raiseOnError);
+    bool loadCurrentExecutable();
+    bool loadResources();
+
+    virtual void logLoaded();
+    virtual bool checkVersion(const char *expected);
+};
+
+class PluginDll : public HelperDll
+{
+    ECLPluginDefinitionBlockEx pb;
+
+public:
+    PluginDll(const char *_name, const IFileIO *_dllFile) : HelperDll(_name, _dllFile) {}
+
+    bool init(IPluginContextEx * pluginCtx);
+
+    virtual bool checkVersion(const char *expected);
+    virtual void logLoaded();
+};
+
+HelperDll::HelperDll(const char *_name, const IFileIO *_dllFile)
+: name(_name), dllFile(_dllFile)
+{
+    logLoad = false;
+}
+
+bool HelperDll::load(bool isGlobal, bool raiseOnError)
+{
+    if (!so.load(name, isGlobal, raiseOnError))
+        return false;
+    return true;
+}
+
+bool HelperDll::loadResources()
+{
+#ifdef _WIN32
+    return so.loadResources(name);
+#else
+    Owned<IFile> file = createIFile(name);
+    mappedDll.setown(file->openMemoryMapped());
+    return mappedDll != nullptr;
+#endif
+}
+
+bool HelperDll::loadCurrentExecutable()
+{
+    if (!so.loadCurrentExecutable())
+        return false;
+    return true;
+}
+
+HelperDll::~HelperDll()
+{
+    if (logLoad)
+        DBGLOG("Unloading dll %s", name.get());
+}
+
+HINSTANCE HelperDll::getInstance() const
+{
+    if (!so.loaded())
+        throw MakeStringException(0, "Dll %s only loaded for resources", name.str());
+    return so.getInstanceHandle();
+}
+
+void * HelperDll::getEntry(const char * entry) const
+{
+    if (!so.loaded())
+        throw MakeStringException(0, "Dll %s only loaded for resources", name.str());
+    return so.getEntry(entry);
+}
+
+bool HelperDll::IsShared()
+{
+    return CInterface::IsShared();
+}
+
+const char * HelperDll::queryVersion() const
+{
+    return "";
+}
+
+void HelperDll::logLoaded()
+{
+    logLoad = true;
+    DBGLOG("Loaded DLL %s", name.get());
+}
+
+bool HelperDll::checkVersion(const char *expected)
+{
+    return true;
+}
+
+const char * HelperDll::queryName() const
+{
+    return name.get();
+}
+
+const byte * HelperDll::getResource(unsigned id) const
+{
+    if (so.loaded())
+    {
+#ifdef _WIN32
+        HINSTANCE dllHandle = so.getInstanceHandle();
+        HRSRC hrsrc = FindResource(dllHandle, MAKEINTRESOURCE(id), "BIGSTRING");
+        if (hrsrc)
+            return (const byte *)LoadResource(dllHandle, hrsrc);
+        return NULL;
+#else
+        StringBuffer resourceName;
+        resourceName.appendf("BIGSTRING_%d_txt_start", id);
+        return (const byte *)getEntry(resourceName.str());
+#endif
+    }
+    else
+    {
+        size32_t len;
+        const void * data;
+        if (getResource(len, data, "BIGSTRING", id, false))
+            return (const byte *)data;
+        return nullptr;
+    }
+}
+
+const byte resourceHeaderVersion=1;
+const size32_t resourceHeaderLength = sizeof(byte) + sizeof(byte) + sizeof(bool) + sizeof(size32_t);
+
+
+bool HelperDll::getResource(size32_t & len, const void * & data, const char * type, unsigned id, bool trace) const
+{
+    if (so.loaded())
+    {
+#ifdef _WIN32
+        HINSTANCE dllHandle = so.getInstanceHandle();
+        HRSRC hrsrc = FindResource(dllHandle, MAKEINTRESOURCE(id), type);
+        if (!hrsrc)
+            return false;
+        len = SizeofResource(dllHandle, hrsrc);
+        data = (const byte *)LoadResource(dllHandle, hrsrc);
+        return true;
+#else
+        StringBuffer symName;
+        symName.append(type).append("_").append(id).append("_txt_start");
+        data = (const void *)getEntry(symName.str());
+        if (!data)
+        {
+            if (trace)
+                printf("Failed to locate symbol %s\n", symName.str());
+            return false;
+        }
+        byte bom;
+        byte version;
+        bool compressed;
+
+        MemoryBuffer mb;
+        mb.setBuffer(resourceHeaderLength, const_cast<void *>(data));
+        mb.read(bom);
+        if (bom != 0x80)
+            return false;
+        mb.read(version);
+        if (version > resourceHeaderVersion)
+            return false;
+        mb.read(compressed).read(len);
+        len += resourceHeaderLength;
+        return true;
+#endif
+    }
+    else
+    {
+#ifdef _WIN32
+        return false;
+#endif
+        if (!mappedDll)
+            return false;
+        return getResourceFromMappedFile(name, mappedDll->base(), len, data, type, id);
+    }
+}
+
+//-------------------------------------------------------------------------------------------------------------------
+
 bool PluginDll::init(IPluginContextEx * pluginCtx)
 {
     HINSTANCE h = getInstance();
@@ -445,10 +500,15 @@ void PluginDll::logLoaded()
     }
 }
 
-extern DLLSERVER_API ILoadedDllEntry * createDllEntry(const char *path, bool isGlobal, const IFileIO *dllFile)
+extern DLLSERVER_API ILoadedDllEntry * createDllEntry(const char *path, bool isGlobal, const IFileIO *dllFile, bool resourcesOnly)
 {
     Owned<HelperDll> result = new HelperDll(path, dllFile);
-    if (!result->load(isGlobal, true))
+    bool ok;
+    if (!resourcesOnly)
+        ok = result->load(isGlobal, true);
+    else
+        ok = result->loadResources();
+    if (!ok)
         throw MakeStringException(0, "Failed to create ILoadedDllEntry for dll %s", path);
     return result.getClear();
 }

+ 2 - 1
common/dllserver/thorplugin.hpp

@@ -33,11 +33,12 @@ interface ILoadedDllEntry : extends IInterface
     virtual bool getResource(size32_t & len, const void * & data, const char * type, unsigned id, bool trace=true) const = 0;
 };
 
-extern DLLSERVER_API ILoadedDllEntry * createDllEntry(const char *name, bool isGlobal, const IFileIO *dllFile);
+extern DLLSERVER_API ILoadedDllEntry * createDllEntry(const char *name, bool isGlobal, const IFileIO *dllFile, bool resourcesOnly);
 extern DLLSERVER_API ILoadedDllEntry * createExeDllEntry(const char *name);
 extern DLLSERVER_API bool getEmbeddedWorkUnitXML(ILoadedDllEntry *dll, StringBuffer &xml);
 extern DLLSERVER_API bool getEmbeddedManifestXML(ILoadedDllEntry *dll, StringBuffer &xml);
 extern DLLSERVER_API bool checkEmbeddedWorkUnitXML(ILoadedDllEntry *dll);
+extern DLLSERVER_API bool getResourceFromFile(const char *filename, MemoryBuffer &data, const char * type, unsigned id);
 extern DLLSERVER_API bool getResourceXMLFromFile(const char *filename, const char *type, unsigned id, StringBuffer &xml);
 extern DLLSERVER_API bool getWorkunitXMLFromFile(const char *filename, StringBuffer &xml);
 extern DLLSERVER_API bool getManifestXMLFromFile(const char *filename, StringBuffer &xml);

+ 1 - 1
common/wuwebview/wuwebview.cpp

@@ -783,7 +783,7 @@ ILoadedDllEntry *WuWebView::loadDll(bool force)
     {
         try
         {
-            dll.setown(queryDllServer().loadDll(dllname.str(), DllLocationAnywhere));
+            dll.setown(queryDllServer().loadDllResources(dllname.str(), DllLocationAnywhere));
         }
         catch (IException *e)
         {

+ 1 - 1
esp/services/esdl_svc_engine/esdl_binding.hpp

@@ -111,7 +111,7 @@ public:
 #ifdef LINK_STATICALLY  // May be useful for debugging...
             javaplugin.setown(javaembed::getEmbedContext());
 #else
-            javaPluginDll.setown(createDllEntry("javaembed", false, NULL));
+            javaPluginDll.setown(createDllEntry("javaembed", false, NULL, false));
             if (!javaPluginDll)
                 throw makeStringException(0, "Failed to load javaembed plugin");
             GetEmbedContextFunction pf = (GetEmbedContextFunction) javaPluginDll->getEntry("getEmbedContextDynamic");

+ 5 - 1
roxie/ccd/ccddali.cpp

@@ -851,7 +851,7 @@ public:
             {
                 try
                 {
-                    return createDllEntry(localName.str(), false, NULL);
+                    return createDllEntry(localName.str(), false, NULL, false);
                 }
                 catch (ICorruptDllException *E)
                 {
@@ -875,6 +875,10 @@ public:
         }
         return queryDllServer().loadDll(name, location);
     }
+    virtual ILoadedDllEntry * loadDllResources(const char * name, DllLocationType location) 
+    {
+        throwUnexpected();
+    }
 } roxieDllServer;
 
 bool CRoxieDaliHelper::isConnected = false;

+ 14 - 0
system/jlib/jutil.cpp

@@ -485,6 +485,20 @@ bool SharedObject::loadCurrentExecutable()
     return true;
 }
 
+bool SharedObject::loadResources(const char * dllName)
+{
+#ifdef _WIN32
+    UINT oldMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+    h = LoadLibraryEx(dllName, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
+    if (!LoadSucceeded(h))
+        h = LoadLibraryEx(dllName, NULL, LOAD_LIBRARY_AS_DATAFILE); // the LOAD_LIBRARY_AS_IMAGE_RESOURCE flag is not supported on all versions of Windows
+    SetErrorMode(oldMode);
+    return LoadSucceeded(h);
+#else
+    UNIMPLEMENTED;
+#endif
+}
+
 void *SharedObject::getEntry(const char * name) const
 {
     return GetSharedProcedure(getInstanceHandle(), name);

+ 2 - 1
system/jlib/jutil.hpp

@@ -73,7 +73,8 @@ public:
     
     bool load(const char * dllName, bool isGlobal, bool raiseOnError=false);
     bool loadCurrentExecutable();
-    bool loaded()       { return h != 0; }
+    bool loadResources(const char * dllName);
+    bool loaded() const { return h != 0; }
     void unload();
     HINSTANCE getInstanceHandle() const { return h; }
     void *getEntry(const char * name) const;

+ 1 - 1
thorlcr/master/thgraphmanager.cpp

@@ -873,7 +873,7 @@ bool CJobManager::executeGraph(IConstWorkUnit &workunit, const char *graphName,
         sendSo = globals->getPropBool("Debug/@dllsToSlaves", true);
     }
 
-    Owned<ILoadedDllEntry> querySo = createDllEntry(compoundPath.str(), false, NULL);
+    Owned<ILoadedDllEntry> querySo = createDllEntry(compoundPath.str(), false, NULL, false);
 
     SCMStringBuffer eclstr;
     StringAttr user(workunit.queryUser());

+ 1 - 1
thorlcr/slave/slavmain.cpp

@@ -346,7 +346,7 @@ public:
                             soPath.clear().append(tempSo.str());
                         }
 #endif
-                        Owned<ILoadedDllEntry> querySo = createDllEntry(soPath.str(), false, NULL);
+                        Owned<ILoadedDllEntry> querySo = createDllEntry(soPath.str(), false, NULL, false);
 
                         Owned<IPropertyTree> workUnitInfo = createPTree(msg);
                         StringBuffer user;