[RFC] portabledeviceapi: Add dll

Fabian Maurer dark.shadow4 at web.de
Fri Nov 9 11:54:28 CST 2018


This is a first try to generalize COM implementations.
I find it useful to not repeat all that code for every
new implementation.

Feedback appreciated, can we go that route?

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=40206
---
 configure                                     |  26 +-
 configure.ac                                  |   1 +
 dlls/portabledeviceapi/Makefile.in            |   7 +
 dlls/portabledeviceapi/portabledeviceapi.c    | 138 ++++++++++
 dlls/portabledeviceapi/portabledeviceapi.spec |   4 +
 .../portabledeviceapi_classes.idl             |  21 ++
 .../portabledeviceapi_private.h               |  26 ++
 include/Makefile.in                           |   1 +
 include/portabledeviceapi.idl                 |  71 +++++
 include/wine/com.h                            | 256 ++++++++++++++++++
 10 files changed, 533 insertions(+), 18 deletions(-)
 create mode 100644 dlls/portabledeviceapi/Makefile.in
 create mode 100644 dlls/portabledeviceapi/portabledeviceapi.c
 create mode 100644 dlls/portabledeviceapi/portabledeviceapi.spec
 create mode 100644 dlls/portabledeviceapi/portabledeviceapi_classes.idl
 create mode 100644 dlls/portabledeviceapi/portabledeviceapi_private.h
 create mode 100644 include/portabledeviceapi.idl
 create mode 100644 include/wine/com.h

diff --git a/configure b/configure
index 7f9786f6eb..b4f79e01cc 100755
--- a/configure
+++ b/configure
@@ -805,7 +805,6 @@ infodir
 docdir
 oldincludedir
 includedir
-runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -1477,6 +1476,7 @@ enable_packager
 enable_pdh
 enable_photometadatahandler
 enable_pidgen
+enable_portabledeviceapi
 enable_powrprof
 enable_printui
 enable_prntvpt
@@ -1879,7 +1879,6 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -2132,15 +2131,6 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
-  -runstatedir | --runstatedir | --runstatedi | --runstated \
-  | --runstate | --runstat | --runsta | --runst | --runs \
-  | --run | --ru | --r)
-    ac_prev=runstatedir ;;
-  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
-  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
-  | --run=* | --ru=* | --r=*)
-    runstatedir=$ac_optarg ;;
-
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -2278,7 +2268,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir runstatedir
+		libdir localedir mandir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -2431,7 +2421,6 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
-  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -6822,7 +6811,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -6868,7 +6857,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -6892,7 +6881,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -6937,7 +6926,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -6961,7 +6950,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -19746,6 +19735,7 @@ wine_fn_config_makefile dlls/pdh enable_pdh
 wine_fn_config_makefile dlls/pdh/tests enable_tests
 wine_fn_config_makefile dlls/photometadatahandler enable_photometadatahandler
 wine_fn_config_makefile dlls/pidgen enable_pidgen
+wine_fn_config_makefile dlls/portabledeviceapi enable_portabledeviceapi
 wine_fn_config_makefile dlls/powrprof enable_powrprof
 wine_fn_config_makefile dlls/printui enable_printui
 wine_fn_config_makefile dlls/prntvpt enable_prntvpt
diff --git a/configure.ac b/configure.ac
index efec221113..a3aa4cb839 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3595,6 +3595,7 @@ WINE_CONFIG_MAKEFILE(dlls/pdh)
 WINE_CONFIG_MAKEFILE(dlls/pdh/tests)
 WINE_CONFIG_MAKEFILE(dlls/photometadatahandler)
 WINE_CONFIG_MAKEFILE(dlls/pidgen)
+WINE_CONFIG_MAKEFILE(dlls/portabledeviceapi)
 WINE_CONFIG_MAKEFILE(dlls/powrprof)
 WINE_CONFIG_MAKEFILE(dlls/printui)
 WINE_CONFIG_MAKEFILE(dlls/prntvpt)
diff --git a/dlls/portabledeviceapi/Makefile.in b/dlls/portabledeviceapi/Makefile.in
new file mode 100644
index 0000000000..f57ef8b57b
--- /dev/null
+++ b/dlls/portabledeviceapi/Makefile.in
@@ -0,0 +1,7 @@
+MODULE    = portabledeviceapi.dll
+IMPORTS   = uuid ole32
+
+C_SRCS = \
+	portabledeviceapi.c
+
+IDL_SRCS = portabledeviceapi_classes.idl
diff --git a/dlls/portabledeviceapi/portabledeviceapi.c b/dlls/portabledeviceapi/portabledeviceapi.c
new file mode 100644
index 0000000000..da91af9aca
--- /dev/null
+++ b/dlls/portabledeviceapi/portabledeviceapi.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(deviceapi);
+
+#define WINE_COM_MAIN
+#include "wine/com.h"
+
+#include "portabledeviceapi_private.h"
+
+#include "initguid.h"
+#include "portabledeviceapi.h"
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+    return com_main(instance, reason, reserved);
+}
+
+static const com_object_creation_info object_creation[] =
+{
+    { &CLSID_PortableDeviceManager, &PortableDeviceManager_create },
+};
+
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
+{
+    return com_get_class_object(object_creation, ARRAY_SIZE(object_creation), rclsid, riid, ppv);
+}
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+    return S_FALSE;
+}
+
+HRESULT WINAPI DllRegisterServer(void)
+{
+    return __wine_register_resources(instance_dll);
+}
+
+HRESULT WINAPI DllUnregisterServer(void)
+{
+    return __wine_unregister_resources(instance_dll);
+}
+
+COM_DEFINE_OBJECT_WITH_SINGLE_INTERFACE(PortableDeviceManager, IPortableDeviceManager)
+COM_DEFINE_QueryInterface(PortableDeviceManager, IPortableDeviceManager)
+COM_DEFINE_AddRef(PortableDeviceManager, IPortableDeviceManager)
+COM_DEFINE_Release(PortableDeviceManager, IPortableDeviceManager)
+
+static HRESULT WINAPI IPortableDeviceManager_impl_GetDevices(IPortableDeviceManager *iface,
+        LPWSTR *pPnPDeviceIDs, DWORD *pcPnPDeviceIDs)
+{
+    FIXME("(%p, %p): stub!\n", pPnPDeviceIDs, pcPnPDeviceIDs);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IPortableDeviceManager_impl_RefreshDeviceList(IPortableDeviceManager *iface)
+{
+    FIXME("(): stub!\n");
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IPortableDeviceManager_impl_GetDeviceFriendlyName(IPortableDeviceManager *iface,
+        LPCWSTR pszPnPDeviceID, WCHAR *pDeviceFriendlyName, DWORD* pcchDeviceFriendlyName)
+{
+    FIXME("(%s, %p): stub!\n", debugstr_w(pszPnPDeviceID), pDeviceFriendlyName);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IPortableDeviceManager_impl_GetDeviceDescription(IPortableDeviceManager *iface,
+        LPCWSTR pszPnPDeviceID, WCHAR *pDeviceDescription, DWORD *pcchDeviceDescription)
+{
+    FIXME("(%s, %p, %p): stub!\n", debugstr_w(pszPnPDeviceID), pDeviceDescription, pcchDeviceDescription);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IPortableDeviceManager_impl_GetDeviceManufacturer(IPortableDeviceManager *iface,
+        LPCWSTR pszPnPDeviceID, WCHAR *pDeviceManufacturer, DWORD *pcchDeviceManufacturer)
+{
+    FIXME("(%s, %p, %p): stub!\n", debugstr_w(pszPnPDeviceID), pDeviceManufacturer, pcchDeviceManufacturer);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IPortableDeviceManager_impl_GetDeviceProperty(IPortableDeviceManager *iface,
+        LPCWSTR pszPnPDeviceID, LPCWSTR pszDevicePropertyName, BYTE *pData, DWORD *pcbData, DWORD *pdwType)
+{
+    FIXME("(%s, %s, %p, %p, %p): stub!\n",
+            debugstr_w(pszPnPDeviceID), debugstr_w(pszDevicePropertyName), pData, pcbData, pdwType);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IPortableDeviceManager_impl_GetPrivateDevices(IPortableDeviceManager *iface,
+        LPWSTR *pPnPDeviceIDs, DWORD *pcPnPDeviceIDs)
+{
+    FIXME("(%p, %p): stub!\n", pPnPDeviceIDs, pcPnPDeviceIDs);
+
+    return E_NOTIMPL;
+}
+
+static const IPortableDeviceManagerVtbl IPortableDeviceManager_vtbl =
+{
+    IPortableDeviceManager_impl_QueryInterface,
+    IPortableDeviceManager_impl_AddRef,
+    IPortableDeviceManager_impl_Release,
+    IPortableDeviceManager_impl_GetDevices,
+    IPortableDeviceManager_impl_RefreshDeviceList,
+    IPortableDeviceManager_impl_GetDeviceFriendlyName,
+    IPortableDeviceManager_impl_GetDeviceDescription,
+    IPortableDeviceManager_impl_GetDeviceManufacturer,
+    IPortableDeviceManager_impl_GetDeviceProperty,
+    IPortableDeviceManager_impl_GetPrivateDevices
+};
+
+COM_DEFINE_CREATE_FOR_OBJECT_WITH_SINGLE_INTERFACE(PortableDeviceManager, IPortableDeviceManager, IPortableDeviceManager_vtbl)
diff --git a/dlls/portabledeviceapi/portabledeviceapi.spec b/dlls/portabledeviceapi/portabledeviceapi.spec
new file mode 100644
index 0000000000..b16365d0c9
--- /dev/null
+++ b/dlls/portabledeviceapi/portabledeviceapi.spec
@@ -0,0 +1,4 @@
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
diff --git a/dlls/portabledeviceapi/portabledeviceapi_classes.idl b/dlls/portabledeviceapi/portabledeviceapi_classes.idl
new file mode 100644
index 0000000000..0da8f228da
--- /dev/null
+++ b/dlls/portabledeviceapi/portabledeviceapi_classes.idl
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma makedep register
+
+#include "portabledeviceapi.idl"
diff --git a/dlls/portabledeviceapi/portabledeviceapi_private.h b/dlls/portabledeviceapi/portabledeviceapi_private.h
new file mode 100644
index 0000000000..0624a814af
--- /dev/null
+++ b/dlls/portabledeviceapi/portabledeviceapi_private.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __PORTABLEDEVICEAPI_PRIVATE_INCLUDED__
+#define __PORTABLEDEVICEAPI_PRIVATE_INCLUDED__
+
+#include "unknwn.h"
+
+HRESULT PortableDeviceManager_create(IUnknown *unk_outer, void **obj) DECLSPEC_HIDDEN;
+
+#endif /* __PORTABLEDEVICEAPI_PRIVATE_INCLUDED__ */
diff --git a/include/Makefile.in b/include/Makefile.in
index cc78b1c154..cf4fa317f0 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -511,6 +511,7 @@ SOURCES = \
 	physicalmonitorenumerationapi.h \
 	pktdef.h \
 	poppack.h \
+	portabledeviceapi.idl \
 	powrprof.h \
 	prntvpt.h \
 	profinfo.h \
diff --git a/include/portabledeviceapi.idl b/include/portabledeviceapi.idl
new file mode 100644
index 0000000000..523da782f0
--- /dev/null
+++ b/include/portabledeviceapi.idl
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "unknwn.idl"
+
+[
+    object,
+    uuid(a1567595-4c2f-4574-a6fa-ecef917b9a40),
+    local
+]
+interface IPortableDeviceManager : IUnknown
+{
+	HRESULT GetDevices(
+		[in, out] LPWSTR *pPnPDeviceIDs,
+		[in, out] DWORD *pcPnPDeviceIDs
+	);
+
+	HRESULT RefreshDeviceList();
+
+	HRESULT GetDeviceFriendlyName(
+		[in] LPCWSTR pszPnPDeviceID,
+		[in, out] WCHAR *pDeviceFriendlyName,
+		[in, out] DWORD *pcchDeviceFriendlyName
+	);
+
+	HRESULT GetDeviceDescription(
+		[in] LPCWSTR pszPnPDeviceID,
+		[in, out] WCHAR *pDeviceDescription,
+		[in, out] DWORD *pcchDeviceDescription
+	);
+
+	HRESULT GetDeviceManufacturer(
+		[in] LPCWSTR pszPnPDeviceID,
+		[in, out] WCHAR *pDeviceManufacturer,
+		[in, out] DWORD *pcchDeviceManufacturer
+	);
+
+	HRESULT GetDeviceProperty(
+		[in] LPCWSTR pszPnPDeviceID,
+		[in] LPCWSTR pszDevicePropertyName,
+		[in, out] BYTE *pData,
+		[in, out] DWORD *pcbData,
+		[in, out] DWORD *pdwType
+	);
+
+	HRESULT GetPrivateDevices(
+		[in, out] LPWSTR *pPnPDeviceIDs,
+		[in, out] DWORD *pcPnPDeviceIDs
+	);
+};
+
+[
+    threading(both),
+    uuid(0af10cec-2ecd-4b92-9581-34f6ae0637f3)
+]
+coclass PortableDeviceManager { interface IPortableDeviceManager; }
diff --git a/include/wine/com.h b/include/wine/com.h
new file mode 100644
index 0000000000..2f73bfcbd0
--- /dev/null
+++ b/include/wine/com.h
@@ -0,0 +1,256 @@
+/*
+ * COM helper functions
+ *
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_WINE_COM_H
+#define __WINE_WINE_COM_H
+
+#define COBJMACROS
+#include "unknwn.h"
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "rpcproxy.h"
+
+#include "wine/debug.h"
+
+#ifdef __WINE_WINE_TEST_H
+#error This file should not be used in Wine tests
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static HINSTANCE instance_dll;
+
+#ifdef WINE_COM_MAIN
+
+typedef struct
+{
+    const CLSID *clsid;
+    HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **ppobj);
+} com_object_creation_info;
+
+typedef struct
+{
+    IClassFactory IClassFactory_iface;
+
+    LONG ref;
+    HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **ppobj);
+} IClassFactoryImpl;
+
+static inline BOOL WINAPI com_main(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+    TRACE("(0x%p, %d, %p)\n", instance, reason, reserved);
+
+    switch (reason)
+    {
+        case DLL_WINE_PREATTACH:
+            return FALSE;    /* prefer native version */
+        case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(instance);
+            instance_dll = instance;
+            break;
+    }
+
+    return TRUE;
+}
+
+static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
+{
+    return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
+}
+
+static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
+{
+    IClassFactoryImpl *impl = impl_from_IClassFactory(iface);
+
+    if (IsEqualGUID(riid, &IID_IUnknown)
+        || IsEqualGUID(riid, &IID_IClassFactory))
+    {
+        IClassFactory_AddRef(iface);
+        *ppobj = &impl->IClassFactory_iface;
+        return S_OK;
+    }
+
+    WARN("(%p)->(%s,%p),not found\n", impl, 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 *impl = impl_from_IClassFactory(iface);
+    ULONG ref = InterlockedDecrement(&impl->ref);
+
+    if (ref == 0)
+        HeapFree(GetProcessHeap(), 0, impl);
+
+    return ref;
+}
+
+static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown *outer_unk, REFIID riid, void **ppobj)
+{
+    IClassFactoryImpl *impl = impl_from_IClassFactory(iface);
+    HRESULT hres;
+    IUnknown *unk;
+
+    TRACE("(%p)->(%p,%s,%p)\n", impl, outer_unk, debugstr_guid(riid), ppobj);
+
+    *ppobj = NULL;
+    hres = impl->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 *impl = impl_from_IClassFactory(iface);
+    FIXME("(%p)->(%d), stub!\n", impl, dolock);
+    return S_OK;
+}
+
+static const IClassFactoryVtbl classfactory_Vtbl =
+{
+    classfactory_QueryInterface,
+    classfactory_AddRef,
+    classfactory_Release,
+    classfactory_CreateInstance,
+    classfactory_LockServer
+};
+
+HRESULT WINAPI com_get_class_object(const com_object_creation_info *object_creation, int object_creation_length,
+        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 < object_creation_length; i++)
+    {
+        if (IsEqualGUID(object_creation[i].clsid, rclsid))
+            break;
+    }
+
+    if (i == object_creation_length)
+    {
+        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;
+}
+
+#endif /* WINE_COM_MAIN */
+
+#define COM_DEFINE_OBJECT_WITH_SINGLE_INTERFACE(CLASS, INTERFACE) \
+    typedef struct {                                                                        \
+        INTERFACE INTERFACE##_iface;                                                        \
+        LONG ref;                                                                           \
+    } CLASS##_impl;                                                                         \
+                                                                                            \
+    static inline CLASS##_impl *impl_from_##INTERFACE(INTERFACE *iface)                     \
+    {                                                                                       \
+        return CONTAINING_RECORD(iface, CLASS##_impl, INTERFACE##_iface);                   \
+    }                                                                                       \
+
+#define COM_DEFINE_QueryInterface(CLASS, INTERFACE) \
+    static HRESULT WINAPI INTERFACE##_impl_QueryInterface(INTERFACE *iface,                 \
+                                                          REFIID riid, void **obj)          \
+    {                                                                                       \
+        CLASS##_impl *impl = impl_from_##INTERFACE(iface);                                  \
+        TRACE("(%p/%p)->(%s,%p)\n", iface, impl, debugstr_guid(riid), obj);                 \
+        if (IsEqualGUID(riid, &IID_IUnknown)                                                \
+            || IsEqualGUID(riid, &IID_##INTERFACE))                                         \
+        {                                                                                   \
+            IUnknown_AddRef(iface);                                                         \
+            *obj = &impl->INTERFACE##_iface;                                                \
+            return S_OK;                                                                    \
+        }                                                                                   \
+        ERR("(%p)->(%s,%p),not found\n", impl, debugstr_guid(riid), obj);                   \
+        return E_NOINTERFACE;                                                               \
+    }
+
+#define COM_DEFINE_AddRef(CLASS, INTERFACE) \
+    static ULONG WINAPI INTERFACE##_impl_AddRef(INTERFACE *iface)                           \
+    {                                                                                       \
+        CLASS##_impl *impl = impl_from_##INTERFACE(iface);                                  \
+        ULONG ref = InterlockedIncrement(&impl->ref);                                       \
+        TRACE("(%p/%p)->(): new ref %d\n", iface, impl, ref);                               \
+        return ref;                                                                         \
+    }                                                                                       \
+
+#define COM_DEFINE_Release(CLASS, INTERFACE) \
+    static ULONG WINAPI INTERFACE##_impl_Release(INTERFACE *iface)                          \
+    {                                                                                       \
+        CLASS##_impl *impl = impl_from_##INTERFACE(iface);                                  \
+        ULONG ref = InterlockedDecrement(&impl->ref);                                       \
+        TRACE("(%p/%p)->(): new ref %d\n", iface, impl, ref);                               \
+        if (!ref)                                                                           \
+            HeapFree(GetProcessHeap(), 0, impl);                                            \
+        return ref;                                                                         \
+    }
+
+#define COM_DEFINE_CREATE_FOR_OBJECT_WITH_SINGLE_INTERFACE(CLASS, INTERFACE, TABLE)         \
+    HRESULT CLASS##_create(IUnknown *unk_outer, void **obj)                                 \
+    {                                                                                       \
+    CLASS##_impl *impl;                                                                     \
+        TRACE("(%p,%p)\n", unk_outer, obj);                                                 \
+        impl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS##_impl));         \
+        if (!impl)                                                                          \
+            return E_OUTOFMEMORY;                                                           \
+        impl->INTERFACE##_iface.lpVtbl = &TABLE;                                            \
+        impl->ref = 1;                                                                      \
+        *obj = &impl->INTERFACE##_iface;                                                    \
+        return S_OK;                                                                        \
+    }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __WINE_WINE_COM_H */
-- 
2.19.1




More information about the wine-devel mailing list