aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/W5S.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/W5S.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/W5S.cpp')
-rw-r--r--Src/Winamp/W5S.cpp226
1 files changed, 226 insertions, 0 deletions
diff --git a/Src/Winamp/W5S.cpp b/Src/Winamp/W5S.cpp
new file mode 100644
index 00000000..131fc438
--- /dev/null
+++ b/Src/Winamp/W5S.cpp
@@ -0,0 +1,226 @@
+#include "Main.h"
+#include "../Agave/Component/ifc_wa5component.h"
+#include <vector>
+#include "api.h"
+#include "LazyServiceFactory.h"
+
+extern LARGE_INTEGER freq;
+std::vector<ifc_wa5component*> systemComponents;
+std::vector<LazyServiceFactory*> lazyFactories;
+
+enum
+{
+ W5S_LOAD = 0,
+ W5S_LAZYLOAD = 1,
+};
+
+static uint32_t magic_word = 0xdeadbeefUL;
+/* layout (binary)
+0xdeadbeef - 32 bits
+service guid - 128 bits
+service fourcc - 32 bits
+length of service name - 16bits
+service name - see previous
+length of test string - 16 bits
+test string - see previous
+repeat as necessary
+*/
+static int w5s_load_binary_manifest(const wchar_t *filename, const wchar_t *w5s_filename)
+{
+ HANDLE manifest = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (manifest != INVALID_HANDLE_VALUE)
+ {
+ for(;;)
+ {
+ uint32_t manifest_magic_word;
+ GUID service_guid;
+ FOURCC service_fourcc;
+
+ DWORD bytesRead=0;
+ ReadFile(manifest, &manifest_magic_word, sizeof(manifest_magic_word), &bytesRead, NULL);
+ if (bytesRead == 0) // EOF
+ {
+ CloseHandle(manifest);
+ return W5S_LAZYLOAD;
+ }
+
+ if (bytesRead != sizeof(manifest_magic_word) || memcmp(&manifest_magic_word, &magic_word, sizeof(magic_word)))
+ break;
+
+ bytesRead=0;
+ ReadFile(manifest, &service_guid, sizeof(service_guid), &bytesRead, NULL);
+ if (bytesRead != sizeof(service_guid))
+ break;
+
+ bytesRead=0;
+ ReadFile(manifest, &service_fourcc, sizeof(service_fourcc), &bytesRead, NULL);
+ if (bytesRead != sizeof(service_fourcc))
+ break;
+
+ uint16_t service_name_length;
+ bytesRead=0;
+ ReadFile(manifest, &service_name_length, sizeof(service_name_length), &bytesRead, NULL);
+ if (bytesRead != sizeof(service_name_length))
+ break;
+
+ char *service_name = 0;
+ if (service_name_length)
+ {
+ service_name = (char *)calloc(service_name_length + 1, sizeof(char));
+ if (service_name)
+ {
+ bytesRead=0;
+ ReadFile(manifest, service_name, service_name_length, &bytesRead, NULL);
+ if (bytesRead != service_name_length)
+ {
+ free(service_name);
+ break;
+ }
+ }
+ }
+
+ uint16_t service_test_string_length;
+ bytesRead=0;
+ ReadFile(manifest, &service_test_string_length, sizeof(service_test_string_length), &bytesRead, NULL);
+ if (bytesRead != sizeof(service_test_string_length))
+ break;
+
+ char *service_test_string = 0;
+ if (service_test_string_length)
+ {
+ service_test_string = (char *)calloc(service_test_string_length + 1, sizeof(char));
+ if (service_name)
+ {
+ bytesRead=0;
+ ReadFile(manifest, service_test_string, service_test_string_length, &bytesRead, NULL);
+ if (bytesRead != service_test_string_length)
+ {
+ free(service_name);
+ free(service_test_string);
+ break;
+ }
+ }
+ }
+
+ // if we got here, we're OK :)
+ LazyServiceFactory *factory = new LazyServiceFactory(service_fourcc, service_guid, service_name, service_test_string, w5s_filename);
+ lazyFactories.push_back(factory);
+ WASABI_API_SVC->service_register(factory);
+ }
+
+ // file seems to be malformed, go ahead and load w5s.
+ // any lazy factories we already loaded will self-destruct when the real services load
+ CloseHandle(manifest);
+ return W5S_LOAD;
+ }
+
+ return W5S_LOAD;
+}
+
+void w5s_load(const wchar_t *filename)
+{
+ HMODULE hLib = LoadLibraryW(filename);
+ if (hLib == NULL)
+ {
+ auto err = GetLastError();
+ }
+
+ if (hLib)
+ {
+ typedef ifc_wa5component *(*W5SGetter)();
+ W5SGetter pr = (W5SGetter)GetProcAddress(hLib,"GetWinamp5SystemComponent");
+ if (pr)
+ {
+ ifc_wa5component *mod = pr();
+ if (mod)
+ {
+ if (g_safeMode)
+ {
+ try
+ {
+ int retval = 0;
+ mod->_dispatch(15, &retval);
+ if (!retval)
+ {
+ FreeLibrary(hLib);
+ return;
+ }
+ }
+ catch(...)
+ {
+ FreeLibrary(hLib);
+ return;
+ }
+ }
+ systemComponents.push_back(mod);
+ mod->hModule = hLib;
+ mod->RegisterServices(WASABI_API_SVC);
+ }
+ }
+ }
+}
+
+void w5s_init()
+{
+ WIN32_FIND_DATAW d = {0};
+ wchar_t dirstr[MAX_PATH] = {0};
+
+ // pre-load so we're definitely available to other services which need this
+ PathCombineW(dirstr, SYSPLUGINDIR, L"wasabi2.w5s");
+ w5s_load(dirstr);
+
+ PathCombineW(dirstr, SYSPLUGINDIR, L"*.W5S");
+ HANDLE h = FindFirstFileW(dirstr, &d);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ // due to how this plug-in works, is better to do a filename check to not load in
+ // safe mode as it otherwise causes the FreeLibrary(..) call to crash Winamp :o(
+ if (g_safeMode)
+ {
+ if (!wcsnicmp(d.cFileName, L"UnicodeTaskbarFix.w5s", 21)) continue;
+ if (!wcsnicmp(d.cFileName, L"fpl.w5s", 7)) continue;
+ if (!wcsnicmp(d.cFileName, L"mpcpl.w5s", 9)) continue;
+ }
+
+ if (lstrcmpiW(L"wasabi2.w5s", d.cFileName))
+ {
+ wchar_t manifeststr[MAX_PATH] = {0}, namestr[MAX_PATH] = {0};
+ PathCombineW(manifeststr, SYSPLUGINDIR, d.cFileName);
+ PathRemoveExtensionW(manifeststr);
+ PathAddExtensionW(manifeststr, L".wbm");
+ PathCombineW(namestr, SYSPLUGINDIR, d.cFileName);
+ if (w5s_load_binary_manifest(manifeststr, namestr) == W5S_LOAD)
+ {
+ w5s_load(namestr);
+ }
+ }
+ }
+ while (FindNextFileW(h, &d));
+ FindClose(h);
+ }
+
+ Wasabi_FindSystemServices();
+}
+
+void w5s_deinit()
+{
+ Wasabi_ForgetSystemServices();
+
+ for ( ifc_wa5component *l_wa5_component : systemComponents )
+ {
+ l_wa5_component->DeregisterServices( WASABI_API_SVC );
+ l_wa5_component = 0;
+ }
+
+ systemComponents.clear();
+
+ //lazyFactories.deleteAll();
+ for ( auto obj : lazyFactories )
+ {
+ delete obj;
+ }
+
+ lazyFactories.clear();
+}