[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