W5S.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include "Main.h"
  2. #include "../Agave/Component/ifc_wa5component.h"
  3. #include <vector>
  4. #include "api.h"
  5. #include "LazyServiceFactory.h"
  6. extern LARGE_INTEGER freq;
  7. std::vector<ifc_wa5component*> systemComponents;
  8. std::vector<LazyServiceFactory*> lazyFactories;
  9. enum
  10. {
  11. W5S_LOAD = 0,
  12. W5S_LAZYLOAD = 1,
  13. };
  14. static uint32_t magic_word = 0xdeadbeefUL;
  15. /* layout (binary)
  16. 0xdeadbeef - 32 bits
  17. service guid - 128 bits
  18. service fourcc - 32 bits
  19. length of service name - 16bits
  20. service name - see previous
  21. length of test string - 16 bits
  22. test string - see previous
  23. repeat as necessary
  24. */
  25. static int w5s_load_binary_manifest(const wchar_t *filename, const wchar_t *w5s_filename)
  26. {
  27. HANDLE manifest = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
  28. if (manifest != INVALID_HANDLE_VALUE)
  29. {
  30. for(;;)
  31. {
  32. uint32_t manifest_magic_word;
  33. GUID service_guid;
  34. FOURCC service_fourcc;
  35. DWORD bytesRead=0;
  36. ReadFile(manifest, &manifest_magic_word, sizeof(manifest_magic_word), &bytesRead, NULL);
  37. if (bytesRead == 0) // EOF
  38. {
  39. CloseHandle(manifest);
  40. return W5S_LAZYLOAD;
  41. }
  42. if (bytesRead != sizeof(manifest_magic_word) || memcmp(&manifest_magic_word, &magic_word, sizeof(magic_word)))
  43. break;
  44. bytesRead=0;
  45. ReadFile(manifest, &service_guid, sizeof(service_guid), &bytesRead, NULL);
  46. if (bytesRead != sizeof(service_guid))
  47. break;
  48. bytesRead=0;
  49. ReadFile(manifest, &service_fourcc, sizeof(service_fourcc), &bytesRead, NULL);
  50. if (bytesRead != sizeof(service_fourcc))
  51. break;
  52. uint16_t service_name_length;
  53. bytesRead=0;
  54. ReadFile(manifest, &service_name_length, sizeof(service_name_length), &bytesRead, NULL);
  55. if (bytesRead != sizeof(service_name_length))
  56. break;
  57. char *service_name = 0;
  58. if (service_name_length)
  59. {
  60. service_name = (char *)calloc(service_name_length + 1, sizeof(char));
  61. if (service_name)
  62. {
  63. bytesRead=0;
  64. ReadFile(manifest, service_name, service_name_length, &bytesRead, NULL);
  65. if (bytesRead != service_name_length)
  66. {
  67. free(service_name);
  68. break;
  69. }
  70. }
  71. }
  72. uint16_t service_test_string_length;
  73. bytesRead=0;
  74. ReadFile(manifest, &service_test_string_length, sizeof(service_test_string_length), &bytesRead, NULL);
  75. if (bytesRead != sizeof(service_test_string_length))
  76. break;
  77. char *service_test_string = 0;
  78. if (service_test_string_length)
  79. {
  80. service_test_string = (char *)calloc(service_test_string_length + 1, sizeof(char));
  81. if (service_name)
  82. {
  83. bytesRead=0;
  84. ReadFile(manifest, service_test_string, service_test_string_length, &bytesRead, NULL);
  85. if (bytesRead != service_test_string_length)
  86. {
  87. free(service_name);
  88. free(service_test_string);
  89. break;
  90. }
  91. }
  92. }
  93. // if we got here, we're OK :)
  94. LazyServiceFactory *factory = new LazyServiceFactory(service_fourcc, service_guid, service_name, service_test_string, w5s_filename);
  95. lazyFactories.push_back(factory);
  96. WASABI_API_SVC->service_register(factory);
  97. }
  98. // file seems to be malformed, go ahead and load w5s.
  99. // any lazy factories we already loaded will self-destruct when the real services load
  100. CloseHandle(manifest);
  101. return W5S_LOAD;
  102. }
  103. return W5S_LOAD;
  104. }
  105. void w5s_load(const wchar_t *filename)
  106. {
  107. HMODULE hLib = LoadLibraryW(filename);
  108. if (hLib == NULL)
  109. {
  110. auto err = GetLastError();
  111. }
  112. if (hLib)
  113. {
  114. typedef ifc_wa5component *(*W5SGetter)();
  115. W5SGetter pr = (W5SGetter)GetProcAddress(hLib,"GetWinamp5SystemComponent");
  116. if (pr)
  117. {
  118. ifc_wa5component *mod = pr();
  119. if (mod)
  120. {
  121. if (g_safeMode)
  122. {
  123. try
  124. {
  125. int retval = 0;
  126. mod->_dispatch(15, &retval);
  127. if (!retval)
  128. {
  129. FreeLibrary(hLib);
  130. return;
  131. }
  132. }
  133. catch(...)
  134. {
  135. FreeLibrary(hLib);
  136. return;
  137. }
  138. }
  139. systemComponents.push_back(mod);
  140. mod->hModule = hLib;
  141. mod->RegisterServices(WASABI_API_SVC);
  142. }
  143. }
  144. }
  145. }
  146. void w5s_init()
  147. {
  148. WIN32_FIND_DATAW d = {0};
  149. wchar_t dirstr[MAX_PATH] = {0};
  150. // pre-load so we're definitely available to other services which need this
  151. PathCombineW(dirstr, SYSPLUGINDIR, L"wasabi2.w5s");
  152. w5s_load(dirstr);
  153. PathCombineW(dirstr, SYSPLUGINDIR, L"*.W5S");
  154. HANDLE h = FindFirstFileW(dirstr, &d);
  155. if (h != INVALID_HANDLE_VALUE)
  156. {
  157. do
  158. {
  159. // due to how this plug-in works, is better to do a filename check to not load in
  160. // safe mode as it otherwise causes the FreeLibrary(..) call to crash Winamp :o(
  161. if (g_safeMode)
  162. {
  163. if (!wcsnicmp(d.cFileName, L"UnicodeTaskbarFix.w5s", 21)) continue;
  164. if (!wcsnicmp(d.cFileName, L"fpl.w5s", 7)) continue;
  165. if (!wcsnicmp(d.cFileName, L"mpcpl.w5s", 9)) continue;
  166. }
  167. if (lstrcmpiW(L"wasabi2.w5s", d.cFileName))
  168. {
  169. wchar_t manifeststr[MAX_PATH] = {0}, namestr[MAX_PATH] = {0};
  170. PathCombineW(manifeststr, SYSPLUGINDIR, d.cFileName);
  171. PathRemoveExtensionW(manifeststr);
  172. PathAddExtensionW(manifeststr, L".wbm");
  173. PathCombineW(namestr, SYSPLUGINDIR, d.cFileName);
  174. if (w5s_load_binary_manifest(manifeststr, namestr) == W5S_LOAD)
  175. {
  176. w5s_load(namestr);
  177. }
  178. }
  179. }
  180. while (FindNextFileW(h, &d));
  181. FindClose(h);
  182. }
  183. Wasabi_FindSystemServices();
  184. }
  185. void w5s_deinit()
  186. {
  187. Wasabi_ForgetSystemServices();
  188. for ( ifc_wa5component *l_wa5_component : systemComponents )
  189. {
  190. l_wa5_component->DeregisterServices( WASABI_API_SVC );
  191. l_wa5_component = 0;
  192. }
  193. systemComponents.clear();
  194. //lazyFactories.deleteAll();
  195. for ( auto obj : lazyFactories )
  196. {
  197. delete obj;
  198. }
  199. lazyFactories.clear();
  200. }