From 9bf4cd8325c43c600a297b3b15d0b246bd79f5e6 Mon Sep 17 00:00:00 2001 From: Fabian Maurer Date: Mon, 23 Oct 2017 19:40:44 +0200 Subject: [PATCH] dx8vb: Add COM classfactory. Signed-off-by: Fabian Maurer Signed-off-by: Alexandre Julliard --- dlls/dx8vb/Makefile.in | 1 + dlls/dx8vb/dx8vb.spec | 8 +-- dlls/dx8vb/main.c | 153 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 4 deletions(-) diff --git a/dlls/dx8vb/Makefile.in b/dlls/dx8vb/Makefile.in index ce3237c9a57..d9f93f96f12 100644 --- a/dlls/dx8vb/Makefile.in +++ b/dlls/dx8vb/Makefile.in @@ -1,4 +1,5 @@ MODULE = dx8vb.dll +IMPORTS = uuid ole32 C_SRCS = \ main.c diff --git a/dlls/dx8vb/dx8vb.spec b/dlls/dx8vb/dx8vb.spec index 973d4b3f20b..bb7c08300b8 100644 --- a/dlls/dx8vb/dx8vb.spec +++ b/dlls/dx8vb/dx8vb.spec @@ -133,7 +133,7 @@ @ stub D3DXMeshIndexBuffer8SetData @ stub D3DXMeshIndexBuffer8GetData @ stub DXCopyMemory -@ stub DllCanUnloadNow -@ stub DllGetClassObject -@ stub DllRegisterServer -@ stub DllUnregisterServer +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() diff --git a/dlls/dx8vb/main.c b/dlls/dx8vb/main.c index 0b60e345ca5..aa6b9436ceb 100644 --- a/dlls/dx8vb/main.c +++ b/dlls/dx8vb/main.c @@ -16,6 +16,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define COBJMACROS + +#include "config.h" + #include #include @@ -24,10 +28,17 @@ #include "winuser.h" #include "winreg.h" +#include "ole2.h" +#include "rpcproxy.h" + +#include "unknwn.h" + #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dx8vb); +static HINSTANCE instance_dx8vb; + BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { TRACE("(0x%p, %d, %p)\n", instance, reason, reserved); @@ -38,8 +49,150 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) return FALSE; /* prefer native version */ case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(instance); + instance_dx8vb = instance; break; } return TRUE; } + +typedef struct { + IClassFactory IClassFactory_iface; + + LONG ref; + HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **ppobj); +} IClassFactoryImpl; + +static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) +{ + return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); +} + +struct object_creation_info +{ + const CLSID *clsid; + HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **ppobj); +}; + +static const struct object_creation_info object_creation[] = +{ + { &GUID_NULL, 0 }, +}; + +static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IClassFactory)) + { + IClassFactory_AddRef(iface); + *ppobj = &This->IClassFactory_iface; + return S_OK; + } + + WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj); + return E_NOINTERFACE; +} + +static ULONG WINAPI classfactory_AddRef(IClassFactory *iface) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI classfactory_Release(IClassFactory *iface) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) + HeapFree(GetProcessHeap(), 0, This); + + return ref; +} + +static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown *outer_unk, REFIID riid, void **ppobj) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + HRESULT hres; + IUnknown *unk; + + TRACE("(%p)->(%p,%s,%p)\n", This, outer_unk, debugstr_guid(riid), ppobj); + + *ppobj = NULL; + hres = This->pfnCreateInstance(outer_unk, (void **) &unk); + if (SUCCEEDED(hres)) + { + hres = IUnknown_QueryInterface(unk, riid, ppobj); + IUnknown_Release(unk); + } + return hres; +} + +static HRESULT WINAPI classfactory_LockServer(IClassFactory *iface, BOOL dolock) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + FIXME("(%p)->(%d), stub!\n", This, dolock); + return S_OK; +} + +static const IClassFactoryVtbl classfactory_Vtbl = +{ + classfactory_QueryInterface, + classfactory_AddRef, + classfactory_Release, + classfactory_CreateInstance, + classfactory_LockServer +}; + +HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) +{ + unsigned int i; + IClassFactoryImpl *factory; + + TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + + if (!IsEqualGUID(&IID_IClassFactory, riid) + && !IsEqualGUID( &IID_IUnknown, riid)) + return E_NOINTERFACE; + + for (i = 0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) + { + if (IsEqualGUID(object_creation[i].clsid, rclsid)) + break; + } + + if (i == sizeof(object_creation)/sizeof(object_creation[0])) + { + FIXME("%s: no class found.\n", debugstr_guid(rclsid)); + return CLASS_E_CLASSNOTAVAILABLE; + } + + factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory)); + if (factory == NULL) + return E_OUTOFMEMORY; + + factory->IClassFactory_iface.lpVtbl = &classfactory_Vtbl; + factory->ref = 1; + + factory->pfnCreateInstance = object_creation[i].pfnCreateInstance; + + *ppv = &factory->IClassFactory_iface; + return S_OK; +} + +HRESULT WINAPI DllCanUnloadNow(void) +{ + return S_FALSE; +} + +HRESULT WINAPI DllRegisterServer(void) +{ + return __wine_register_resources(instance_dx8vb); +} + +HRESULT WINAPI DllUnregisterServer(void) +{ + return __wine_unregister_resources(instance_dx8vb); +}