ddraw/tests: Use compare_uint() in compare_float() instead of abs().
[wine.git] / programs / dllhost / dllhost.c
blob9e3455ee15ab74f6f0907e979f814b76e77454c6
1 /*
2 * Copyright 2022 Dmitry Timoshkov
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.
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.
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
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include <windef.h>
24 #include <winbase.h>
25 #include <objbase.h>
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dllhost);
31 struct factory
33 IClassFactory IClassFactory_iface;
34 IMarshal IMarshal_iface;
35 CLSID clsid;
36 LONG ref;
37 IClassFactory *dll_factory;
40 static inline struct factory *impl_from_IClassFactory(IClassFactory *iface)
42 return CONTAINING_RECORD(iface, struct factory, IClassFactory_iface);
45 static inline struct factory *impl_from_IMarshal(IMarshal *iface)
47 return CONTAINING_RECORD(iface, struct factory, IMarshal_iface);
50 static HRESULT WINAPI factory_QueryInterface(IClassFactory *iface,
51 REFIID iid, void **ppv)
53 struct factory *factory = impl_from_IClassFactory(iface);
55 TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
57 if (!ppv) return E_INVALIDARG;
59 if (IsEqualIID(iid, &IID_IUnknown) ||
60 IsEqualIID(iid, &IID_IClassFactory))
62 IClassFactory_AddRef(&factory->IClassFactory_iface);
63 *ppv = &factory->IClassFactory_iface;
64 return S_OK;
66 else if (IsEqualIID(iid, &IID_IMarshal))
68 IClassFactory_AddRef(&factory->IClassFactory_iface);
69 *ppv = &factory->IMarshal_iface;
70 return S_OK;
73 *ppv = NULL;
74 return E_NOINTERFACE;
77 static ULONG WINAPI factory_AddRef(IClassFactory *iface)
79 struct factory *factory = impl_from_IClassFactory(iface);
80 ULONG ref = InterlockedIncrement(&factory->ref);
82 TRACE("(%p)->%lu\n", iface, ref);
83 return ref;
86 static ULONG WINAPI factory_Release(IClassFactory *iface)
88 struct factory *factory = impl_from_IClassFactory(iface);
89 ULONG ref = InterlockedDecrement(&factory->ref);
91 TRACE("(%p)->%lu\n", iface, ref);
93 if (!ref)
95 if (factory->dll_factory) IClassFactory_Release(factory->dll_factory);
96 HeapFree(GetProcessHeap(), 0, factory);
99 return ref;
102 static HRESULT WINAPI factory_CreateInstance(IClassFactory *iface,
103 IUnknown *punkouter, REFIID iid, void **ppv)
105 FIXME("(%p,%p,%s,%p): stub\n", iface, punkouter, wine_dbgstr_guid(iid), ppv);
106 return E_NOTIMPL;
109 static HRESULT WINAPI factory_LockServer(IClassFactory *iface, BOOL lock)
111 TRACE("(%p,%d)\n", iface, lock);
112 return S_OK;
115 static const IClassFactoryVtbl ClassFactory_Vtbl =
117 factory_QueryInterface,
118 factory_AddRef,
119 factory_Release,
120 factory_CreateInstance,
121 factory_LockServer
124 static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, LPVOID *ppv)
126 struct factory *factory = impl_from_IMarshal(iface);
128 TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
130 return IClassFactory_QueryInterface(&factory->IClassFactory_iface, iid, ppv);
133 static ULONG WINAPI marshal_AddRef(IMarshal *iface)
135 struct factory *factory = impl_from_IMarshal(iface);
137 TRACE("(%p)\n", iface);
139 return IClassFactory_AddRef(&factory->IClassFactory_iface);
142 static ULONG WINAPI marshal_Release(IMarshal *iface)
144 struct factory *factory = impl_from_IMarshal(iface);
146 TRACE("(%p)\n", iface);
148 return IClassFactory_Release(&factory->IClassFactory_iface);
151 static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *pv,
152 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
154 TRACE("(%p,%s,%p,%08lx,%p,%08lx,%p)\n", iface, wine_dbgstr_guid(iid), pv,
155 dwDestContext, pvDestContext, mshlflags, clsid);
157 *clsid = CLSID_StdMarshal;
158 return S_OK;
161 static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *pv,
162 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
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;
169 static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
170 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
172 struct factory *factory = impl_from_IMarshal(iface);
174 TRACE("(%p,%s,%p,%08lx,%p,%08lx)\n", stream, wine_dbgstr_guid(iid), pv, dwDestContext, pvDestContext, mshlflags);
176 return CoMarshalInterface(stream, iid, (IUnknown *)factory->dll_factory, dwDestContext, pvDestContext, mshlflags);
179 static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
180 REFIID iid, void **ppv)
182 FIXME("(%p,%p,%s,%p): stub\n", iface, stream, wine_dbgstr_guid(iid), ppv);
183 return E_NOTIMPL;
186 static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
188 TRACE("(%p,%p)\n", iface, stream);
189 return S_OK;
192 static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD reserved)
194 TRACE("(%p, %08lx)\n", iface, reserved);
195 return S_OK;
198 static const IMarshalVtbl Marshal_Vtbl =
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
211 struct surrogate
213 ISurrogate ISurrogate_iface;
214 IClassFactory *factory;
215 DWORD cookie;
216 HANDLE event;
217 LONG ref;
220 static inline struct surrogate *impl_from_ISurrogate(ISurrogate *iface)
222 return CONTAINING_RECORD(iface, struct surrogate, ISurrogate_iface);
225 static HRESULT WINAPI surrogate_QueryInterface(ISurrogate *iface,
226 REFIID iid, void **ppv)
228 struct surrogate *surrogate = impl_from_ISurrogate(iface);
230 TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
232 if (!ppv) return E_INVALIDARG;
234 if (IsEqualIID(iid, &IID_IUnknown) ||
235 IsEqualIID(iid, &IID_ISurrogate))
237 ISurrogate_AddRef(&surrogate->ISurrogate_iface);
238 *ppv = &surrogate->ISurrogate_iface;
239 return S_OK;
242 *ppv = NULL;
243 return E_NOINTERFACE;
246 static ULONG WINAPI surrogate_AddRef(ISurrogate *iface)
248 TRACE("(%p)\n", iface);
249 return 2;
252 static ULONG WINAPI surrogate_Release(ISurrogate *iface)
254 TRACE("(%p)\n", iface);
255 return 1;
258 static HRESULT WINAPI surrogate_LoadDllServer(ISurrogate *iface, const CLSID *clsid)
260 struct surrogate *surrogate = impl_from_ISurrogate(iface);
261 struct factory *factory;
262 HRESULT hr;
264 TRACE("(%p,%s)\n", iface, wine_dbgstr_guid(clsid));
266 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
267 if (!factory)
268 return E_OUTOFMEMORY;
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;
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
284 surrogate->factory = &factory->IClassFactory_iface;
285 surrogate->event = CreateEventW(NULL, FALSE, FALSE, NULL);
288 return hr;
291 static HRESULT WINAPI surrogate_FreeSurrogate(ISurrogate *iface)
293 struct surrogate *surrogate = impl_from_ISurrogate(iface);
295 TRACE("(%p)\n", iface);
297 if (surrogate->cookie)
299 CoRevokeClassObject(surrogate->cookie);
300 surrogate->cookie = 0;
303 if (surrogate->factory)
305 IClassFactory_Release(surrogate->factory);
306 surrogate->factory = NULL;
309 SetEvent(surrogate->event);
311 return S_OK;
314 static const ISurrogateVtbl Surrogate_Vtbl =
316 surrogate_QueryInterface,
317 surrogate_AddRef,
318 surrogate_Release,
319 surrogate_LoadDllServer,
320 surrogate_FreeSurrogate
323 int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE previnst, LPWSTR cmdline, int showcmd)
325 HRESULT hr;
326 CLSID clsid;
327 struct surrogate surrogate;
329 TRACE("Running as %u-bit\n", (int)sizeof(void *) * 8);
331 if (wcsnicmp(cmdline, L"/PROCESSID:", 11))
332 return 0;
334 cmdline += 11;
336 surrogate.ISurrogate_iface.lpVtbl = &Surrogate_Vtbl;
337 surrogate.factory = NULL;
338 surrogate.cookie = 0;
339 surrogate.event = NULL;
340 surrogate.ref = 1;
342 CoInitializeEx(NULL, COINIT_MULTITHREADED);
344 hr = CLSIDFromString(cmdline, &clsid);
345 if (hr == S_OK)
347 CoRegisterSurrogate(&surrogate.ISurrogate_iface);
349 hr = ISurrogate_LoadDllServer(&surrogate.ISurrogate_iface, &clsid);
350 if (hr != S_OK)
352 ERR("Can't create instance of %s\n", wine_dbgstr_guid(&clsid));
353 goto cleanup;
356 while (WaitForSingleObject(surrogate.event, 30000) != WAIT_OBJECT_0)
357 CoFreeUnusedLibraries();
360 cleanup:
361 CoUninitialize();
363 return 0;