ntdll: Initialize the system locale on the Unix side.
[wine.git] / programs / dllhost / dllhost.c
blob83700826f8bccce638978dd329daceabaad55fb8
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;
39 static inline struct factory *impl_from_IClassFactory(IClassFactory *iface)
41 return CONTAINING_RECORD(iface, struct factory, IClassFactory_iface);
44 static inline struct factory *impl_from_IMarshal(IMarshal *iface)
46 return CONTAINING_RECORD(iface, struct factory, IMarshal_iface);
49 static HRESULT WINAPI factory_QueryInterface(IClassFactory *iface,
50 REFIID iid, void **ppv)
52 struct factory *factory = impl_from_IClassFactory(iface);
54 TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
56 if (!ppv) return E_INVALIDARG;
58 if (IsEqualIID(iid, &IID_IUnknown) ||
59 IsEqualIID(iid, &IID_IClassFactory))
61 IClassFactory_AddRef(&factory->IClassFactory_iface);
62 *ppv = &factory->IClassFactory_iface;
63 return S_OK;
65 else if (IsEqualIID(iid, &IID_IMarshal))
67 IClassFactory_AddRef(&factory->IClassFactory_iface);
68 *ppv = &factory->IMarshal_iface;
69 return S_OK;
72 *ppv = NULL;
73 return E_NOINTERFACE;
76 static ULONG WINAPI factory_AddRef(IClassFactory *iface)
78 struct factory *factory = impl_from_IClassFactory(iface);
79 ULONG ref = InterlockedIncrement(&factory->ref);
81 TRACE("(%p)->%lu\n", iface, ref);
82 return ref;
85 static ULONG WINAPI factory_Release(IClassFactory *iface)
87 struct factory *factory = impl_from_IClassFactory(iface);
88 ULONG ref = InterlockedDecrement(&factory->ref);
90 TRACE("(%p)->%lu\n", iface, ref);
92 if (!ref)
93 HeapFree(GetProcessHeap(), 0, factory);
95 return ref;
98 static HRESULT WINAPI factory_CreateInstance(IClassFactory *iface,
99 IUnknown *punkouter, REFIID iid, void **ppv)
101 FIXME("(%p,%p,%s,%p): stub\n", iface, punkouter, wine_dbgstr_guid(iid), ppv);
102 return E_NOTIMPL;
105 static HRESULT WINAPI factory_LockServer(IClassFactory *iface, BOOL lock)
107 TRACE("(%p,%d)\n", iface, lock);
108 return S_OK;
111 static const IClassFactoryVtbl ClassFactory_Vtbl =
113 factory_QueryInterface,
114 factory_AddRef,
115 factory_Release,
116 factory_CreateInstance,
117 factory_LockServer
120 static HRESULT WINAPI marshal_QueryInterface(IMarshal *iface, REFIID iid, LPVOID *ppv)
122 struct factory *factory = impl_from_IMarshal(iface);
124 TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
126 return IClassFactory_QueryInterface(&factory->IClassFactory_iface, iid, ppv);
129 static ULONG WINAPI marshal_AddRef(IMarshal *iface)
131 struct factory *factory = impl_from_IMarshal(iface);
133 TRACE("(%p)\n", iface);
135 return IClassFactory_AddRef(&factory->IClassFactory_iface);
138 static ULONG WINAPI marshal_Release(IMarshal *iface)
140 struct factory *factory = impl_from_IMarshal(iface);
142 TRACE("(%p)\n", iface);
144 return IClassFactory_Release(&factory->IClassFactory_iface);
147 static HRESULT WINAPI marshal_GetUnmarshalClass(IMarshal *iface, REFIID iid, void *pv,
148 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
150 TRACE("(%p,%s,%p,%08lx,%p,%08lx,%p)\n", iface, wine_dbgstr_guid(iid), pv,
151 dwDestContext, pvDestContext, mshlflags, clsid);
153 *clsid = CLSID_StdMarshal;
154 return S_OK;
157 static HRESULT WINAPI marshal_GetMarshalSizeMax(IMarshal *iface, REFIID iid, void *pv,
158 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
160 FIXME("(%p,%s,%p,%08lx,%p,%08lx,%p): stub\n", iface, wine_dbgstr_guid(iid), pv,
161 dwDestContext, pvDestContext, mshlflags, size);
162 return E_NOTIMPL;
165 static HRESULT WINAPI marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID iid,
166 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
168 struct factory *factory = impl_from_IMarshal(iface);
169 IUnknown *object;
170 HRESULT hr;
172 TRACE("(%p,%s,%p,%08lx,%p,%08lx)\n", stream, wine_dbgstr_guid(iid), pv, dwDestContext, pvDestContext, mshlflags);
174 hr = CoGetClassObject(&factory->clsid, CLSCTX_INPROC_SERVER, NULL, iid, (void **)&object);
175 if (hr == S_OK)
177 hr = CoMarshalInterface(stream, iid, object, dwDestContext, pvDestContext, mshlflags);
178 IUnknown_Release(object);
180 return hr;
183 static HRESULT WINAPI marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
184 REFIID iid, void **ppv)
186 FIXME("(%p,%p,%s,%p): stub\n", iface, stream, wine_dbgstr_guid(iid), ppv);
187 return E_NOTIMPL;
190 static HRESULT WINAPI marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
192 TRACE("(%p,%p)\n", iface, stream);
193 return S_OK;
196 static HRESULT WINAPI marshal_DisconnectObject(IMarshal *iface, DWORD reserved)
198 TRACE("(%p, %08lx)\n", iface, reserved);
199 return S_OK;
202 static const IMarshalVtbl Marshal_Vtbl =
204 marshal_QueryInterface,
205 marshal_AddRef,
206 marshal_Release,
207 marshal_GetUnmarshalClass,
208 marshal_GetMarshalSizeMax,
209 marshal_MarshalInterface,
210 marshal_UnmarshalInterface,
211 marshal_ReleaseMarshalData,
212 marshal_DisconnectObject
215 struct surrogate
217 ISurrogate ISurrogate_iface;
218 IClassFactory *factory;
219 DWORD cookie;
220 HANDLE event;
221 LONG ref;
224 static inline struct surrogate *impl_from_ISurrogate(ISurrogate *iface)
226 return CONTAINING_RECORD(iface, struct surrogate, ISurrogate_iface);
229 static HRESULT WINAPI surrogate_QueryInterface(ISurrogate *iface,
230 REFIID iid, void **ppv)
232 struct surrogate *surrogate = impl_from_ISurrogate(iface);
234 TRACE("(%p,%s,%p)\n", iface, wine_dbgstr_guid(iid), ppv);
236 if (!ppv) return E_INVALIDARG;
238 if (IsEqualIID(iid, &IID_IUnknown) ||
239 IsEqualIID(iid, &IID_ISurrogate))
241 ISurrogate_AddRef(&surrogate->ISurrogate_iface);
242 *ppv = &surrogate->ISurrogate_iface;
243 return S_OK;
246 *ppv = NULL;
247 return E_NOINTERFACE;
250 static ULONG WINAPI surrogate_AddRef(ISurrogate *iface)
252 TRACE("(%p)\n", iface);
253 return 2;
256 static ULONG WINAPI surrogate_Release(ISurrogate *iface)
258 TRACE("(%p)\n", iface);
259 return 1;
262 static HRESULT WINAPI surrogate_LoadDllServer(ISurrogate *iface, const CLSID *clsid)
264 struct surrogate *surrogate = impl_from_ISurrogate(iface);
265 struct factory *factory;
266 HRESULT hr;
268 TRACE("(%p,%s)\n", iface, wine_dbgstr_guid(clsid));
270 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
271 if (!factory)
272 return E_OUTOFMEMORY;
274 factory->IClassFactory_iface.lpVtbl = &ClassFactory_Vtbl;
275 factory->IMarshal_iface.lpVtbl = &Marshal_Vtbl;
276 factory->clsid = *clsid;
277 factory->ref = 1;
279 hr = CoRegisterClassObject(clsid, (IUnknown *)&factory->IClassFactory_iface,
280 CLSCTX_LOCAL_SERVER, REGCLS_SURROGATE, &surrogate->cookie);
281 if (hr != S_OK)
282 IClassFactory_Release(&factory->IClassFactory_iface);
283 else
285 surrogate->factory = &factory->IClassFactory_iface;
286 surrogate->event = CreateEventW(NULL, FALSE, FALSE, NULL);
289 return hr;
292 static HRESULT WINAPI surrogate_FreeSurrogate(ISurrogate *iface)
294 struct surrogate *surrogate = impl_from_ISurrogate(iface);
296 TRACE("(%p)\n", iface);
298 if (surrogate->cookie)
300 CoRevokeClassObject(surrogate->cookie);
301 surrogate->cookie = 0;
304 if (surrogate->factory)
306 IClassFactory_Release(surrogate->factory);
307 surrogate->factory = NULL;
310 SetEvent(surrogate->event);
312 return S_OK;
315 static const ISurrogateVtbl Surrogate_Vtbl =
317 surrogate_QueryInterface,
318 surrogate_AddRef,
319 surrogate_Release,
320 surrogate_LoadDllServer,
321 surrogate_FreeSurrogate
324 int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE previnst, LPWSTR cmdline, int showcmd)
326 HRESULT hr;
327 CLSID clsid;
328 struct surrogate surrogate;
330 TRACE("Running as %u-bit\n", (int)sizeof(void *) * 8);
332 if (wcsnicmp(cmdline, L"/PROCESSID:", 11))
333 return 0;
335 cmdline += 11;
337 surrogate.ISurrogate_iface.lpVtbl = &Surrogate_Vtbl;
338 surrogate.factory = NULL;
339 surrogate.cookie = 0;
340 surrogate.event = NULL;
341 surrogate.ref = 1;
343 CoInitializeEx(NULL, COINIT_MULTITHREADED);
345 hr = CLSIDFromString(cmdline, &clsid);
346 if (hr == S_OK)
348 CoRegisterSurrogate(&surrogate.ISurrogate_iface);
350 hr = ISurrogate_LoadDllServer(&surrogate.ISurrogate_iface, &clsid);
351 if (hr != S_OK)
353 ERR("Can't create instance of %s\n", wine_dbgstr_guid(&clsid));
354 goto cleanup;
357 while (WaitForSingleObject(surrogate.event, 30000) != WAIT_OBJECT_0)
358 CoFreeUnusedLibraries();
361 cleanup:
362 CoUninitialize();
364 return 0;