OSDN Git Service

Generate Unpacker Plugins from Editor script functions
authorTakashi Sawanaka <sdottaka@users.sourceforge.net>
Wed, 5 May 2021 13:38:48 +0000 (22:38 +0900)
committerTakashi Sawanaka <sdottaka@users.sourceforge.net>
Wed, 5 May 2021 13:38:48 +0000 (22:38 +0900)
Src/Common/lwdisp.c
Src/Plugins.cpp
Src/PluginsListDlg.cpp
Src/SelectUnpackerDlg.cpp

index 6c38bc0..df1776e 100644 (file)
@@ -451,7 +451,7 @@ STDAPI invokeV(LPDISPATCH pi, VARIANT *ret, DISPID id, LPCCH op, VARIANT *argv)
                        }
                        else
                        {
-                               ReportError(excepInfo.scode, MB_ICONSTOP|MB_TASKMODAL);
+                               ReportError(excepInfo.scode == 0 ? sc : excepInfo.scode, MB_ICONSTOP|MB_TASKMODAL);
                        }
                        SysFreeString(excepInfo.bstrDescription);
                        SysFreeString(excepInfo.bstrSource);
index 30750b4..940a156 100644 (file)
@@ -37,6 +37,8 @@
 #include "coretools.h"
 #include "OptionsMgr.h"
 #include "OptionsDef.h"
+#include "codepage_detect.h"
+#include "UniFile.h"
 
 using std::vector;
 using Poco::RegularExpression;
@@ -373,6 +375,134 @@ static String GetCustomFilters(const String& name, const String& filtersTextDefa
                return filtersTextDefault;
 }
 
+class UnpackerGeneratedFromEditorScript: public IDispatch
+{
+public:
+       UnpackerGeneratedFromEditorScript(IDispatch *pDispatch, int id) : m_pDispatch(pDispatch), m_funcid(id), m_nRef(0)
+       {
+               m_pDispatch->AddRef();
+       }
+
+       HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override
+       {
+               return E_NOTIMPL;
+       }
+
+       ULONG STDMETHODCALLTYPE AddRef(void) override
+       {
+               return ++m_nRef;
+       }
+
+       ULONG STDMETHODCALLTYPE Release(void) override
+       {
+               if (--m_nRef == 0)
+               {
+                       m_pDispatch->Release();
+                       delete this;
+                       return 0;
+               }
+               return m_nRef;
+       }
+
+       HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override
+       {
+               for (unsigned i = 0; i < cNames; ++i)
+                       rgDispId[i] = (wcscmp(L"UnpackFile", rgszNames[i]) == 0) ? 1 : -1;
+               return S_OK;
+       }
+
+       static HRESULT ReadFile(const String& path, String& text)
+       {
+               UniMemFile file;
+               if (!file.OpenReadOnly(path))
+                       return E_ACCESSDENIED;
+               file.ReadBom();
+               if (!file.HasBom())
+               {
+                       int iGuessEncodingType = GetOptionsMgr()->GetInt(OPT_CP_DETECT);
+                       FileTextEncoding encoding = codepage_detect::Guess(
+                               paths::FindExtension(path), file.GetBase(),
+                               file.GetFileSize() < codepage_detect::BufSize ? file.GetFileSize() : codepage_detect::BufSize,
+                               iGuessEncodingType);
+                       file.SetCodepage(encoding.m_codepage);
+               }
+               file.ReadStringAll(text);
+               file.Close();
+               return S_OK;
+       }
+
+       static HRESULT WriteFile(const String& path, const String& text)
+       {
+               UniStdioFile fileOut;
+               if (!fileOut.Open(path, _T("wb")))
+                       return E_ACCESSDENIED;
+               fileOut.SetUnicoding(ucr::UNICODESET::UTF8);
+               fileOut.SetBom(true);
+               fileOut.WriteBom();
+               fileOut.WriteString(text);
+               fileOut.Close();
+               return S_OK;
+       }
+
+       HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override
+       {
+               if (!pDispParams)
+                       return DISP_E_BADVARTYPE;
+               if (dispIdMember != 1)
+                       return E_NOTIMPL;
+
+               BSTR dstPath = pDispParams->rgvarg[2].bstrVal;
+               BSTR srcPath = pDispParams->rgvarg[3].bstrVal;
+
+               int changed = 0;
+               String text;
+               HRESULT hr = ReadFile(srcPath, text);
+               if (FAILED(hr))
+                       return hr;
+               if (!plugin::InvokeTransformText(text, changed, m_pDispatch, m_funcid))
+                       return E_FAIL;
+               hr = WriteFile(dstPath, text);
+               if (FAILED(hr))
+                       return hr;
+
+               *pDispParams->rgvarg[1].pboolVal = VARIANT_TRUE;
+               pVarResult->boolVal = VARIANT_TRUE;
+               return S_OK;
+       }
+
+       static PluginInfoPtr MakePluginInfo(PluginInfo *pPluginBase, const String& funcname, int fncid)
+       {
+               PluginInfoPtr plugin(new PluginInfo);
+               plugin->m_lpDispatch = new UnpackerGeneratedFromEditorScript(pPluginBase->m_lpDispatch, fncid);
+               plugin->m_lpDispatch->AddRef();
+               plugin->m_name = pPluginBase->m_name + _T(":") + funcname;
+               plugin->m_description =
+                       strutils::format_string2(_T("Unpacker to execute %1 script (automatically generated from %2)")
+                               , funcname, pPluginBase->m_name);
+               plugin->m_disabled = false;
+               plugin->m_filtersTextDefault = _T(".");
+               plugin->m_filtersText = GetCustomFilters(plugin->m_name, plugin->m_filtersTextDefault);
+               plugin->m_bAutomatic = true;
+               plugin->m_event = L"FILE_PACK_UNPACK";
+               return plugin;
+       }
+
+private:
+       IDispatch *m_pDispatch;
+       int m_funcid;
+       int m_nRef;
+};
+
 /**
  * @brief Tiny structure that remembers current scriptlet & event info for calling Log
  */
@@ -721,6 +851,24 @@ static std::map<String, PluginArrayPtr> GetAvailableScripts()
                }
        }
 
+       if (plugins.find(L"EDITOR_SCRIPT") != plugins.end())
+       {
+               for (auto plugin : *plugins[L"EDITOR_SCRIPT"])
+               {
+                       std::vector<String> namesArray;
+                       std::vector<int> idArray;
+                       int validFuncs = plugin::GetMethodsFromScript(plugin->m_lpDispatch, namesArray, idArray);
+                       for (int i = 0; i < validFuncs; ++i)
+                       {
+                               if (plugins.find(L"FILE_PACK_UNPACK") == plugins.end())
+                                       plugins[L"FILE_PACK_UNPACK"].reset(new PluginArray);
+                               PluginInfoPtr pluginNew = UnpackerGeneratedFromEditorScript::MakePluginInfo(plugin.get(), namesArray[i], idArray[i]);
+                               pluginNew->m_disabled = (disabled_plugin_list.find(pluginNew->m_name) != disabled_plugin_list.end());
+                               plugins[L"FILE_PACK_UNPACK"]->push_back(pluginNew);
+                       }
+               }
+       }
+
        // Remove any bad plugins from the cache
        // This might be a good time to see if the user wants to abort or continue
        while (!badScriptlets.empty())
index 815dc24..47c2e09 100644 (file)
@@ -96,9 +96,9 @@ void PluginsListDlg::InitList()
 void PluginsListDlg::AddPlugins()
 {
        String type = _("Unpacker");
+       AddPluginsToList(L"FILE_FOLDER_PACK_UNPACK", type);
        AddPluginsToList(L"FILE_PACK_UNPACK", type);
        AddPluginsToList(L"BUFFER_PACK_UNPACK", type);
-       AddPluginsToList(L"FILE_FOLDER_PACK_UNPACK", type);
        type = _("Prediffer");
        AddPluginsToList(L"FILE_PREDIFF", type);
        AddPluginsToList(L"BUFFER_PREDIFF", type);
index 7e04839..9f6c533 100644 (file)
@@ -57,28 +57,28 @@ void CSelectUnpackerDlg::Initialize()
        m_UnpackerPlugins.Add(automaticPlugin.get());
        // add the real unpackers to the unpackers list
        size_t i;
-       for (i = 0 ; i < piFileScriptArray->size() ; i++)
+       for (i = 0 ; i < piFileFolderScriptArray->size() ; i++)
        {
                // during the dialog, we use a pointer to the scriptsOfThreads array
-               const PluginInfoPtr& plugin = piFileScriptArray->at(i);
+               const PluginInfoPtr& plugin = piFileFolderScriptArray->at(i);
                if (!plugin->m_disabled)
                {
                        m_UnpackerPlugins.Add(plugin.get());
                }
        }
-       for (i = 0 ; i < piBufferScriptArray->size() ; i++)
+       for (i = 0 ; i < piFileScriptArray->size() ; i++)
        {
                // during the dialog, we use a pointer to the scriptsOfThreads array
-               const PluginInfoPtr& plugin = piBufferScriptArray->at(i);
+               const PluginInfoPtr& plugin = piFileScriptArray->at(i);
                if (!plugin->m_disabled)
                {
                        m_UnpackerPlugins.Add(plugin.get());
                }
        }
-       for (i = 0 ; i < piFileFolderScriptArray->size() ; i++)
+       for (i = 0 ; i < piBufferScriptArray->size() ; i++)
        {
                // during the dialog, we use a pointer to the scriptsOfThreads array
-               const PluginInfoPtr& plugin = piFileFolderScriptArray->at(i);
+               const PluginInfoPtr& plugin = piBufferScriptArray->at(i);
                if (!plugin->m_disabled)
                {
                        m_UnpackerPlugins.Add(plugin.get());