diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/W5S.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Winamp/W5S.cpp')
-rw-r--r-- | Src/Winamp/W5S.cpp | 226 |
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(); +} |