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