LazyServiceFactory.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "LazyServiceFactory.h"
  2. #include "w5s.h"
  3. #include "api.h"
  4. #include <strsafe.h>
  5. /*
  6. various implementation notes:
  7. 1) register for service notifications after registering service, so we can know if our service got loaded indirectly
  8. */
  9. LazyServiceFactory::LazyServiceFactory(FOURCC _service_type, GUID _service_guid, char *_service_name, char *_service_test_string, const wchar_t *_service_filename)
  10. {
  11. service_type=_service_type;
  12. service_guid=_service_guid;
  13. service_name=_service_name;
  14. service_test_string = _service_test_string;
  15. StringCbCopyW(service_filename, sizeof(service_filename), _service_filename);
  16. }
  17. LazyServiceFactory::~LazyServiceFactory()
  18. {
  19. WASABI_API_SVC->service_deregister(this);
  20. free(service_name);
  21. free(service_test_string);
  22. }
  23. FOURCC LazyServiceFactory::GetServiceType()
  24. {
  25. return service_type;
  26. }
  27. const char *LazyServiceFactory::GetServiceName()
  28. {
  29. return service_name;
  30. }
  31. GUID LazyServiceFactory::GetGUID()
  32. {
  33. return service_guid;
  34. }
  35. void *LazyServiceFactory::GetInterface(int global_lock)
  36. {
  37. //load target W5S
  38. w5s_load(service_filename);
  39. // ask the service manager remove our service factory and put the new one in our old place (to keep enumeration valid)
  40. WASABI_API_SVC->service_compactDuplicates(this);
  41. // call the service manager to get the "real" service which should now (hopefully) be loaded
  42. waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(service_guid);
  43. if (sf && sf != this)
  44. return sf->getInterface();
  45. return 0;
  46. }
  47. int LazyServiceFactory::SupportNonLockingInterface()
  48. {
  49. return 1;
  50. }
  51. int LazyServiceFactory::ReleaseInterface(void *ifc)
  52. {
  53. // someone may have held on to our service factory when they loaded the service
  54. // so they call us instead of the real service factory
  55. // so go grab the 'real' service and release through that
  56. waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(service_guid);
  57. if (sf && sf != this) // make sure we didn't just grab ourselves :)
  58. {
  59. return sf->releaseInterface(ifc);
  60. }
  61. return 0;
  62. }
  63. const char *LazyServiceFactory::GetTestString()
  64. {
  65. return service_test_string;
  66. }
  67. int LazyServiceFactory::ServiceNotify(int msg, intptr_t param1, intptr_t param2)
  68. {
  69. switch (msg)
  70. {
  71. case SvcNotify::ONDEREGISTERED:
  72. WASABI_API_SYSCB->syscb_deregisterCallback(this);
  73. break;
  74. case SvcNotify::ONREGISTERED:
  75. WASABI_API_SYSCB->syscb_registerCallback(this);
  76. break;
  77. }
  78. return 1;
  79. }
  80. int LazyServiceFactory::Notify(int msg, intptr_t param1, intptr_t param2)
  81. {
  82. switch (msg)
  83. {
  84. case SvcCallback::ONREGISTER:
  85. {
  86. waServiceFactory *sf = reinterpret_cast<waServiceFactory*>(param2);
  87. GUID serviceGUID = sf->getGuid();
  88. if (sf != this && serviceGUID != INVALID_GUID && serviceGUID == service_guid)
  89. {
  90. // real service got loaded, so unregister ourselves
  91. WASABI_API_SVC->service_compactDuplicates(this);
  92. }
  93. }
  94. break;
  95. default: return 0;
  96. }
  97. return 1;
  98. }
  99. #define CBCLASS LazyServiceFactory
  100. START_MULTIPATCH;
  101. START_PATCH(ServiceFactoryPatch)
  102. M_CB(ServiceFactoryPatch, waServiceFactory, WASERVICEFACTORY_GETSERVICETYPE, GetServiceType);
  103. M_CB(ServiceFactoryPatch, waServiceFactory, WASERVICEFACTORY_GETSERVICENAME, GetServiceName);
  104. M_CB(ServiceFactoryPatch, waServiceFactory, WASERVICEFACTORY_GETGUID, GetGUID);
  105. M_CB(ServiceFactoryPatch, waServiceFactory, WASERVICEFACTORY_GETINTERFACE, GetInterface);
  106. M_CB(ServiceFactoryPatch, waServiceFactory, WASERVICEFACTORY_SUPPORTNONLOCKINGGETINTERFACE, SupportNonLockingInterface) ;
  107. M_CB(ServiceFactoryPatch, waServiceFactory, WASERVICEFACTORY_RELEASEINTERFACE, ReleaseInterface);
  108. M_CB(ServiceFactoryPatch, waServiceFactory, WASERVICEFACTORY_GETTESTSTRING, GetTestString);
  109. M_CB(ServiceFactoryPatch, waServiceFactory, WASERVICEFACTORY_SERVICENOTIFY, ServiceNotify);
  110. NEXT_PATCH(SysCallbackPatch)
  111. M_CB(SysCallbackPatch, SysCallback, SYSCALLBACK_GETEVENTTYPE, GetEventType);
  112. M_CB(SysCallbackPatch, SysCallback, SYSCALLBACK_NOTIFY, Notify);
  113. END_PATCH
  114. END_MULTIPATCH;
  115. #undef CBCLASS