Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/programs/dllhost/dllhost.c
4389 views
1
/*
2
* Copyright 2022 Dmitry Timoshkov
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*/
18
19
#include <stdarg.h>
20
21
#define COBJMACROS
22
23
#include <windef.h>
24
#include <winbase.h>
25
#include <objbase.h>
26
27
#include "wine/debug.h"
28
29
WINE_DEFAULT_DEBUG_CHANNEL(dllhost);
30
31
struct factory
32
{
33
IClassFactory IClassFactory_iface;
34
IMarshal IMarshal_iface;
35
CLSID clsid;
36
LONG ref;
37
IClassFactory *dll_factory;
38
};
39
40
static inline struct factory *impl_from_IClassFactory(IClassFactory *iface)
41
{
42
return CONTAINING_RECORD(iface, struct factory, IClassFactory_iface);
43
}
44
45
static inline struct factory *impl_from_IMarshal(IMarshal *iface)
46
{
47
return CONTAINING_RECORD(iface, struct factory, IMarshal_iface);
48
}
49
50
static HRESULT WINAPI factory_QueryInterface(IClassFactory *iface,
51
REFIID iid, void **ppv)
52
{
53
struct factory *factory = impl_from_IClassFactory(iface);
54
55
TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
56
57
if (!ppv) return E_INVALIDARG;
58
59
if (IsEqualIID(iid, &IID_IUnknown) ||
60
IsEqualIID(iid, &IID_IClassFactory))
61
{
62
IClassFactory_AddRef(&factory->IClassFactory_iface);
63
*ppv = &factory->IClassFactory_iface;
64
return S_OK;
65
}
66
else if (IsEqualIID(iid, &IID_IMarshal))
67
{
68
IClassFactory_AddRef(&factory->IClassFactory_iface);
69
*ppv = &factory->IMarshal_iface;
70
return S_OK;
71
}
72
73
*ppv = NULL;
74
return E_NOINTERFACE;
75
}
76
77
static ULONG WINAPI factory_AddRef(IClassFactory *iface)
78
{
79
struct factory *factory = impl_from_IClassFactory(iface);
80
ULONG ref = InterlockedIncrement(&factory->ref);
81
82
TRACE("(%p)->%lu\n", iface, ref);
83
return ref;
84
}
85
86
static ULONG WINAPI factory_Release(IClassFactory *iface)
87
{
88
struct factory *factory = impl_from_IClassFactory(iface);
89
ULONG ref = InterlockedDecrement(&factory->ref);
90
91
TRACE("(%p)->%lu\n", iface, ref);
92
93
if (!ref)
94
{
95
if (factory->dll_factory) IClassFactory_Release(factory->dll_factory);
96
HeapFree(GetProcessHeap(), 0, factory);
97
}
98
99
return ref;
100
}
101
102
static HRESULT WINAPI factory_CreateInstance(IClassFactory *iface,
103
IUnknown *punkouter, REFIID iid, void **ppv)
104
{
105
FIXME("(%p,%p,%s,%p): stub\n", iface, punkouter, wine_dbgstr_guid(iid), ppv);
106
return E_NOTIMPL;
107
}
108
109
static HRESULT WINAPI factory_LockServer(IClassFactory *iface, BOOL lock)
110
{
111
TRACE("(%p,%d)\n", iface, lock);
112
return S_OK;
113
}
114
115
static const IClassFactoryVtbl ClassFactory_Vtbl =
116
{
117
factory_QueryInterface,
118
factory_AddRef,
119
factory_Release,
120
factory_CreateInstance,
121
factory_LockServer
122
};
123
124
static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, LPVOID *ppv)
125
{
126
struct factory *factory = impl_from_IMarshal(iface);
127
128
TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
129
130
return IClassFactory_QueryInterface(&factory->IClassFactory_iface, iid, ppv);
131
}
132
133
static ULONG WINAPI marshal_AddRef(IMarshal *iface)
134
{
135
struct factory *factory = impl_from_IMarshal(iface);
136
137
TRACE("(%p)\n", iface);
138
139
return IClassFactory_AddRef(&factory->IClassFactory_iface);
140
}
141
142
static ULONG WINAPI marshal_Release(IMarshal *iface)
143
{
144
struct factory *factory = impl_from_IMarshal(iface);
145
146
TRACE("(%p)\n", iface);
147
148
return IClassFactory_Release(&factory->IClassFactory_iface);
149
}
150
151
static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *pv,
152
DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
153
{
154
TRACE("(%p,%s,%p,%08lx,%p,%08lx,%p)\n", iface, wine_dbgstr_guid(iid), pv,
155
dwDestContext, pvDestContext, mshlflags, clsid);
156
157
*clsid = CLSID_StdMarshal;
158
return S_OK;
159
}
160
161
static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *pv,
162
DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
163
{
164
FIXME("(%p,%s,%p,%08lx,%p,%08lx,%p): stub\n", iface, wine_dbgstr_guid(iid), pv,
165
dwDestContext, pvDestContext, mshlflags, size);
166
return E_NOTIMPL;
167
}
168
169
static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
170
void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
171
{
172
struct factory *factory = impl_from_IMarshal(iface);
173
174
TRACE("(%p,%s,%p,%08lx,%p,%08lx)\n", stream, wine_dbgstr_guid(iid), pv, dwDestContext, pvDestContext, mshlflags);
175
176
return CoMarshalInterface(stream, iid, (IUnknown *)factory->dll_factory, dwDestContext, pvDestContext, mshlflags);
177
}
178
179
static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
180
REFIID iid, void **ppv)
181
{
182
FIXME("(%p,%p,%s,%p): stub\n", iface, stream, wine_dbgstr_guid(iid), ppv);
183
return E_NOTIMPL;
184
}
185
186
static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
187
{
188
TRACE("(%p,%p)\n", iface, stream);
189
return S_OK;
190
}
191
192
static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD reserved)
193
{
194
TRACE("(%p, %08lx)\n", iface, reserved);
195
return S_OK;
196
}
197
198
static const IMarshalVtbl Marshal_Vtbl =
199
{
200
marshal_QueryInterface,
201
marshal_AddRef,
202
marshal_Release,
203
marshal_GetUnmarshalClass,
204
marshal_GetMarshalSizeMax,
205
marshal_MarshalInterface,
206
marshal_UnmarshalInterface,
207
marshal_ReleaseMarshalData,
208
marshal_DisconnectObject
209
};
210
211
struct surrogate
212
{
213
ISurrogate ISurrogate_iface;
214
IClassFactory *factory;
215
DWORD cookie;
216
HANDLE event;
217
LONG ref;
218
};
219
220
static inline struct surrogate *impl_from_ISurrogate(ISurrogate *iface)
221
{
222
return CONTAINING_RECORD(iface, struct surrogate, ISurrogate_iface);
223
}
224
225
static HRESULT WINAPI surrogate_QueryInterface(ISurrogate *iface,
226
REFIID iid, void **ppv)
227
{
228
struct surrogate *surrogate = impl_from_ISurrogate(iface);
229
230
TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
231
232
if (!ppv) return E_INVALIDARG;
233
234
if (IsEqualIID(iid, &IID_IUnknown) ||
235
IsEqualIID(iid, &IID_ISurrogate))
236
{
237
ISurrogate_AddRef(&surrogate->ISurrogate_iface);
238
*ppv = &surrogate->ISurrogate_iface;
239
return S_OK;
240
}
241
242
*ppv = NULL;
243
return E_NOINTERFACE;
244
}
245
246
static ULONG WINAPI surrogate_AddRef(ISurrogate *iface)
247
{
248
TRACE("(%p)\n", iface);
249
return 2;
250
}
251
252
static ULONG WINAPI surrogate_Release(ISurrogate *iface)
253
{
254
TRACE("(%p)\n", iface);
255
return 1;
256
}
257
258
static HRESULT WINAPI surrogate_LoadDllServer(ISurrogate *iface, const CLSID *clsid)
259
{
260
struct surrogate *surrogate = impl_from_ISurrogate(iface);
261
struct factory *factory;
262
HRESULT hr;
263
264
TRACE("(%p,%s)\n", iface, wine_dbgstr_guid(clsid));
265
266
factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
267
if (!factory)
268
return E_OUTOFMEMORY;
269
270
factory->IClassFactory_iface.lpVtbl = &ClassFactory_Vtbl;
271
factory->IMarshal_iface.lpVtbl = &Marshal_Vtbl;
272
factory->clsid = *clsid;
273
factory->ref = 1;
274
factory->dll_factory = NULL;
275
276
hr = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void **)&factory->dll_factory);
277
if (SUCCEEDED(hr))
278
hr = CoRegisterClassObject(clsid, (IUnknown *)&factory->IClassFactory_iface,
279
CLSCTX_LOCAL_SERVER, REGCLS_SURROGATE, &surrogate->cookie);
280
if (FAILED(hr))
281
IClassFactory_Release(&factory->IClassFactory_iface);
282
else
283
{
284
surrogate->factory = &factory->IClassFactory_iface;
285
surrogate->event = CreateEventW(NULL, FALSE, FALSE, NULL);
286
}
287
288
return hr;
289
}
290
291
static HRESULT WINAPI surrogate_FreeSurrogate(ISurrogate *iface)
292
{
293
struct surrogate *surrogate = impl_from_ISurrogate(iface);
294
295
TRACE("(%p)\n", iface);
296
297
if (surrogate->cookie)
298
{
299
CoRevokeClassObject(surrogate->cookie);
300
surrogate->cookie = 0;
301
}
302
303
if (surrogate->factory)
304
{
305
IClassFactory_Release(surrogate->factory);
306
surrogate->factory = NULL;
307
}
308
309
SetEvent(surrogate->event);
310
311
return S_OK;
312
}
313
314
static const ISurrogateVtbl Surrogate_Vtbl =
315
{
316
surrogate_QueryInterface,
317
surrogate_AddRef,
318
surrogate_Release,
319
surrogate_LoadDllServer,
320
surrogate_FreeSurrogate
321
};
322
323
int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE previnst, LPWSTR cmdline, int showcmd)
324
{
325
HRESULT hr;
326
CLSID clsid;
327
struct surrogate surrogate;
328
329
TRACE("Running as %u-bit\n", (int)sizeof(void *) * 8);
330
331
if (wcsnicmp(cmdline, L"/PROCESSID:", 11))
332
return 0;
333
334
cmdline += 11;
335
336
surrogate.ISurrogate_iface.lpVtbl = &Surrogate_Vtbl;
337
surrogate.factory = NULL;
338
surrogate.cookie = 0;
339
surrogate.event = NULL;
340
surrogate.ref = 1;
341
342
CoInitializeEx(NULL, COINIT_MULTITHREADED);
343
344
hr = CLSIDFromString(cmdline, &clsid);
345
if (hr == S_OK)
346
{
347
CoRegisterSurrogate(&surrogate.ISurrogate_iface);
348
349
hr = ISurrogate_LoadDllServer(&surrogate.ISurrogate_iface, &clsid);
350
if (hr != S_OK)
351
{
352
ERR("Can't create instance of %s\n", wine_dbgstr_guid(&clsid));
353
goto cleanup;
354
}
355
356
while (WaitForSingleObject(surrogate.event, 30000) != WAIT_OBJECT_0)
357
CoFreeUnusedLibraries();
358
}
359
360
cleanup:
361
CoUninitialize();
362
363
return 0;
364
}
365
366