diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-06-14 00:50:34 +0100 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-06-14 00:50:34 +0100 |
commit | 37e364b2c6cc7487a1c888d256a73e5337bb7189 (patch) | |
tree | eaf6e857382eef16c2dd940eb4125536fbe068bd /src/T2DLL/T2PluginLoader.cpp | |
download | t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.tar.gz t2win-37e364b2c6cc7487a1c888d256a73e5337bb7189.zip |
initial commit
Diffstat (limited to '')
-rw-r--r-- | src/T2DLL/T2PluginLoader.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/src/T2DLL/T2PluginLoader.cpp b/src/T2DLL/T2PluginLoader.cpp new file mode 100644 index 0000000..57867ed --- /dev/null +++ b/src/T2DLL/T2PluginLoader.cpp @@ -0,0 +1,214 @@ +#include "CT2App.h" +#include "GlobalFunc.h" +#include "T2PluginLoader.h" +#include "T2PluginSpecifier.h" + +T2PluginLoader::T2PluginLoader() { +} + +T2PluginLoader::~T2PluginLoader() { + POSITION p = mList.GetHeadPosition(); + while (p) { + T2PluginSpecifier *spec = (T2PluginSpecifier *) mList.GetNext(p); + if (spec->mIsLoaded) + UnloadPlugin(spec); + delete spec; + } +} + +void T2PluginLoader::InitFileList() { + char *dirBuf = (char *) malloc(1000); + GetTowerDirectory(dirBuf); + strcat(dirBuf, "Plugins\\"); + char *dirBufEnd = &dirBuf[strlen(dirBuf)]; + + CString dbPath = GetTowerDirectory() + "plugins\\Database"; + BOOL errorFlag = false; + + CFile file; + if (file.Open(dbPath, CFile::modeRead)) { + CArchive archive(&file, CArchive::load); + + DWORD count = mList.GetCount(); + archive >> count; + + for (unsigned int i = 0; i < count; i++) { + T2PluginSpecifier *spec = new T2PluginSpecifier; + spec->Read(archive); + mList.AddTail(spec); + } + + archive.Close(); + file.Close(); + + // check that the database is up-to-date + CFileStatus status; + int count2 = 0; + + POSITION p = mList.GetHeadPosition(); + while (p) { + T2PluginSpecifier *spec = (T2PluginSpecifier *) mList.GetNext(p); + if (CFile::GetStatus(spec->mPath, status)) { + if (status.m_mtime == spec->mTime) + count2++; + } + } + + if (count2 != mList.GetCount()) + errorFlag = true; + + count2 = 0; + + strcpy(dirBufEnd, "*.t2p"); + WIN32_FIND_DATA findData; + HANDLE findHandle = FindFirstFile(dirBuf, &findData); + BOOL findOK = (findHandle != INVALID_HANDLE_VALUE); + while (findOK) { + findOK = FindNextFile(findHandle, &findData); + count2++; + } + FindClose(findHandle); + + if (count2 != mList.GetCount()) + errorFlag = true; + } else { + errorFlag = true; + } + + if (errorFlag) { + // update the DB + AfxSetResourceHandle(gT2App->m_hInstance); + + CDialog *dialog = new CDialog; + dialog->Create(1000); + gT2App->app_vfB4(); + + POSITION p = mList.GetHeadPosition(); + while (p) { + T2PluginSpecifier *spec = (T2PluginSpecifier *) mList.GetNext(p); + delete spec; + } + mList.RemoveAll(); + + strcpy(dirBufEnd, "*.t2p"); + WIN32_FIND_DATA findData; + HANDLE findHandle = FindFirstFile(dirBuf, &findData); + BOOL findOK = (findHandle != INVALID_HANDLE_VALUE); + while (findOK) { + strcpy(dirBufEnd, findData.cFileName); + + T2PluginSpecifier *spec = new T2PluginSpecifier; + spec->Initialize(NULL, dirBuf); + spec->mInstance = NULL; + spec->mIsLoaded = false; + mList.AddTail(spec); + + findOK = FindNextFile(findHandle, &findData); + } + FindClose(findHandle); + + if (file.Open(dbPath, CFile::modeWrite | CFile::modeCreate)) { + CArchive archive(&file, CArchive::store); + + DWORD count = mList.GetCount(); + archive << count; + + p = mList.GetHeadPosition(); + while (p) { + T2PluginSpecifier *spec = (T2PluginSpecifier *) mList.GetNext(p); + spec->Write(archive); + } + + archive.Close(); + file.Close(); + } + + dialog->DestroyWindow(); + } + + free(dirBuf); +} + +typedef void *(MSVC_STDCALL* ConstructProgramPluginType) (T2PluginSpecifier *); +typedef void (MSVC_STDCALL* DestructProgramPluginType) (void); + +/*static*/ void* T2PluginLoader::LoadPlugin(T2PluginSpecifier* spec) { + if (!spec->mIsLoaded) { + HMODULE module = LoadLibrary(spec->mPath); + spec->mInstance = (HINSTANCE) module; + } + + ConstructProgramPluginType func = (ConstructProgramPluginType) GetProcAddress((HMODULE) spec->mInstance, "ConstructProgramPlugin"); +#line 142 + _ASSERT(func); + + spec->mIsLoaded = true; + return func(spec); +} + +/*static*/ void T2PluginLoader::UnloadPlugin(T2PluginSpecifier* spec) { + if (spec->mIsSubPlugin) { + spec->mIsLoaded = false; + return; + } + +#line 154 + _ASSERT(spec->mIsLoaded); + DestructProgramPluginType func = (DestructProgramPluginType) GetProcAddress((HMODULE) spec->mInstance, "DestructProgramPlugin"); +#line 156 + _ASSERT(func); + + spec->mIsLoaded = false; + func(); + FreeLibrary((HMODULE) spec->mInstance); +} + +void T2PluginLoader::SetTypeFilter(POSITION& p, DWORD type) { + p = mList.GetHeadPosition(); + + if (type) + mTypeFilter = type; + else + mTypeFilter = 0; +} + +T2PluginSpecifier* T2PluginLoader::GetNext(POSITION& p) { + while (p) { + T2PluginSpecifier *spec = (T2PluginSpecifier *) mList.GetNext(p); + if ( + (mTypeFilter == 0 || spec->mType == mTypeFilter) && + (spec->m28 == -1 || spec->m28 == 1) // 1 might be a version constant here + ) + return spec; + } + + return NULL; +} + +T2PluginSpecifier* T2PluginLoader::FindPlugin(DWORD id, DWORD type) { + POSITION p; + T2PluginSpecifier *spec; + + SetTypeFilter(p, type); + + while ((spec = GetNext(p))) { + if (spec->mID == id) + return spec; + } + + return NULL; +} + +T2PluginSpecifier* T2PluginLoader::FindPlugin(const char* name, DWORD type) { + POSITION p; + T2PluginSpecifier *spec; + + SetTypeFilter(p, type); + + while ((spec = GetNext(p))) { + if (spec->mPluginName == name) + return spec; + } + + return NULL; +} |