Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/dsdmo/Makefile.in | 5 +-
dlls/dsdmo/dsdmo_classes.idl | 28 +++
dlls/dsdmo/dsdmo_private.h | 32 +++
dlls/dsdmo/echo.c | 397 +++++++++++++++++++++++++++++++++++
dlls/dsdmo/main.c | 57 ++++-
5 files changed, 517 insertions(+), 2 deletions(-)
create mode 100644 dlls/dsdmo/dsdmo_classes.idl
create mode 100644 dlls/dsdmo/dsdmo_private.h
create mode 100644 dlls/dsdmo/echo.c
diff --git a/dlls/dsdmo/Makefile.in b/dlls/dsdmo/Makefile.in
index 99816ae0c0..cb4f8f8a4b 100644
--- a/dlls/dsdmo/Makefile.in
+++ b/dlls/dsdmo/Makefile.in
@@ -1,6 +1,9 @@
MODULE = dsdmo.dll
-
+IMPORTS = uuid
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
+ echo.c \
main.c
+
+IDL_SRCS = dsdmo_classes.idl
diff --git a/dlls/dsdmo/dsdmo_classes.idl b/dlls/dsdmo/dsdmo_classes.idl
new file mode 100644
index 0000000000..649db8f61b
--- /dev/null
+++ b/dlls/dsdmo/dsdmo_classes.idl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2019 Alistair Leslie-Hughes
+ *
+ * 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
+
+[
+ uuid(ef3e932c-d40b-4f51-8ccf-3f98f1b29d5d),
+ threading(both),
+ progid("Microsoft.DirectSoundEchoDMO.1"),
+ vi_progid("Microsoft.DirectSoundEchoDMO")
+]
+coclass DirectSoundEchoDMO
+{
+}
diff --git a/dlls/dsdmo/dsdmo_private.h b/dlls/dsdmo/dsdmo_private.h
new file mode 100644
index 0000000000..4abe5a9f60
--- /dev/null
+++ b/dlls/dsdmo/dsdmo_private.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 Alistair Leslie-Hughes
+ *
+ * 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_DSDMO_PRIVATE
+#define WINE_DSDMO_PRIVATE
+
+#include "windows.h"
+#include "mmsystem.h"
+#include "mediaobj.h"
+
+#include "wine/heap.h"
+#include "wine/debug.h"
+
+#include "dsound.h"
+
+extern HRESULT WINAPI EchoFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv) DECLSPEC_HIDDEN;
+
+#endif
diff --git a/dlls/dsdmo/echo.c b/dlls/dsdmo/echo.c
new file mode 100644
index 0000000000..3e8b0be115
--- /dev/null
+++ b/dlls/dsdmo/echo.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright 2019 Alistair Leslie-Hughes
+ *
+ * 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
+ */
+#define COBJMACROS
+
+#include "dsdmo_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dsdmo);
+
+struct dmo_echofx
+{
+ IDirectSoundFXEcho IDirectSoundFXEcho_iface;
+ IMediaObject IMediaObject_iface;
+ IMediaObjectInPlace IMediaObjectInPlace_iface;
+ LONG ref;
+};
+
+static inline struct dmo_echofx *impl_from_IDirectSoundFXEcho(IDirectSoundFXEcho *iface)
+{
+ return CONTAINING_RECORD(iface, struct dmo_echofx, IDirectSoundFXEcho_iface);
+}
+
+static inline struct dmo_echofx *impl_from_IMediaObject(IMediaObject *iface)
+{
+ return CONTAINING_RECORD(iface, struct dmo_echofx, IMediaObject_iface);
+}
+
+static inline struct dmo_echofx *impl_from_IMediaObjectInPlace(IMediaObjectInPlace *iface)
+{
+ return CONTAINING_RECORD(iface, struct dmo_echofx, IMediaObjectInPlace_iface);
+}
+
+static HRESULT WINAPI echo_mediaobj_QueryInterface(IMediaObject *iface, REFIID riid, void **obj)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ return IDirectSoundFXEcho_QueryInterface(&This->IDirectSoundFXEcho_iface, riid, obj);
+}
+
+static ULONG WINAPI echo_mediaobj_AddRef(IMediaObject *iface)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ return IDirectSoundFXEcho_AddRef(&This->IDirectSoundFXEcho_iface);
+}
+
+static ULONG WINAPI echo_mediaobj_Release(IMediaObject *iface)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ return IDirectSoundFXEcho_Release(&This->IDirectSoundFXEcho_iface);
+}
+
+static HRESULT WINAPI echo_mediaobj_GetStreamCount(IMediaObject *iface, DWORD *inputs, DWORD *outputs)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %p, %p\n", This, inputs, outputs);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p\n", This, index, flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p\n", This, index, flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetInputType(IMediaObject *iface, DWORD index, DWORD type, DMO_MEDIA_TYPE *pmt)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %d, %p\n", This, index, type, pmt);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetOutputType(IMediaObject *iface, DWORD index, DWORD type, DMO_MEDIA_TYPE *pmt)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %d, %p\n", This, index, type, pmt);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_SetInputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *pmt, DWORD flags)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p, %x\n", This, index, pmt, flags);
+ return S_OK;
+}
+
+static HRESULT WINAPI echo_mediaobj_SetOutputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *pmt, DWORD flags)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p, %x\n", This, index, pmt, flags);
+ return S_OK;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *pmt)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p\n", This, index, pmt);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *pmt)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p\n", This, index, pmt);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *ahead, DWORD *alignment)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p, %p, %p\n", This, index, size, ahead, alignment);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p, %p\n", This, index, size, alignment);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p\n", This, index, latency);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %s\n", This, index, wine_dbgstr_longlong(latency));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_Flush(IMediaObject *iface)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_Discontinuity(IMediaObject *iface, DWORD index)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d\n", This, index);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_AllocateStreamingResources(IMediaObject *iface)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_FreeStreamingResources(IMediaObject *iface)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p\n", This, index, flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_ProcessInput(IMediaObject *iface, DWORD index, IMediaBuffer *buffer,
+ DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME length)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d, %p, %x, %s, %s\n", This, index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(length));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count,
+ DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %x, %d, %p, %p\n", This, flags, count, buffers, status);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediaobj_Lock(IMediaObject *iface, LONG lock)
+{
+ struct dmo_echofx *This = impl_from_IMediaObject(iface);
+ FIXME("%p, %d\n", This, lock);
+ return E_NOTIMPL;
+}
+
+static const IMediaObjectVtbl echo_mediaobjectVtbl =
+{
+ echo_mediaobj_QueryInterface,
+ echo_mediaobj_AddRef,
+ echo_mediaobj_Release,
+ echo_mediaobj_GetStreamCount,
+ echo_mediaobj_GetInputStreamInfo,
+ echo_mediaobj_GetOutputStreamInfo,
+ echo_mediaobj_GetInputType,
+ echo_mediaobj_GetOutputType,
+ echo_mediaobj_SetInputType,
+ echo_mediaobj_SetOutputType,
+ echo_mediaobj_GetInputCurrentType,
+ echo_mediaobj_GetOutputCurrentType,
+ echo_mediaobj_GetInputSizeInfo,
+ echo_mediaobj_GetOutputSizeInfo,
+ echo_mediaobj_GetInputMaxLatency,
+ echo_mediaobj_SetInputMaxLatency,
+ echo_mediaobj_Flush,
+ echo_mediaobj_Discontinuity,
+ echo_mediaobj_AllocateStreamingResources,
+ echo_mediaobj_FreeStreamingResources,
+ echo_mediaobj_GetInputStatus,
+ echo_mediaobj_ProcessInput,
+ echo_mediaobj_ProcessOutput,
+ echo_mediaobj_Lock
+};
+
+static HRESULT WINAPI echo_mediainplace_QueryInterface(IMediaObjectInPlace *iface, REFIID riid, void **obj)
+{
+ struct dmo_echofx *This = impl_from_IMediaObjectInPlace(iface);
+ return IDirectSoundFXEcho_QueryInterface(&This->IDirectSoundFXEcho_iface, riid, obj);
+}
+
+static ULONG WINAPI echo_mediainplace_AddRef(IMediaObjectInPlace *iface)
+{
+ struct dmo_echofx *This = impl_from_IMediaObjectInPlace(iface);
+ return IDirectSoundFXEcho_AddRef(&This->IDirectSoundFXEcho_iface);
+}
+
+static ULONG WINAPI echo_mediainplace_Release(IMediaObjectInPlace *iface)
+{
+ struct dmo_echofx *This = impl_from_IMediaObjectInPlace(iface);
+ return IDirectSoundFXEcho_Release(&This->IDirectSoundFXEcho_iface);
+}
+
+static HRESULT WINAPI echo_mediainplace_Process(IMediaObjectInPlace *iface, ULONG size, BYTE *data, REFERENCE_TIME start, DWORD flags)
+{
+ struct dmo_echofx *This = impl_from_IMediaObjectInPlace(iface);
+ static BOOL once = 0;
+ if(!once++)
+ FIXME("%p, %d, %p, %s, %x\n", This, size, data, wine_dbgstr_longlong(start), flags);
+ else
+ TRACE("%p, %d, %p, %s, %x\n", This, size, data, wine_dbgstr_longlong(start), flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediainplace_Clone(IMediaObjectInPlace *iface, IMediaObjectInPlace **object)
+{
+ struct dmo_echofx *This = impl_from_IMediaObjectInPlace(iface);
+ FIXME("%p, %p\n", This, object);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echo_mediainplace_GetLatency(IMediaObjectInPlace *iface, REFERENCE_TIME *latency)
+{
+ struct dmo_echofx *This = impl_from_IMediaObjectInPlace(iface);
+ FIXME("%p, %p\n", This, latency);
+ return E_NOTIMPL;
+}
+
+static const IMediaObjectInPlaceVtbl echo_mediainplaceVtbl =
+{
+ echo_mediainplace_QueryInterface,
+ echo_mediainplace_AddRef,
+ echo_mediainplace_Release,
+ echo_mediainplace_Process,
+ echo_mediainplace_Clone,
+ echo_mediainplace_GetLatency
+};
+
+static HRESULT WINAPI echofx_QueryInterface(IDirectSoundFXEcho *iface, REFIID riid, void **ppv)
+{
+ struct dmo_echofx *This = impl_from_IDirectSoundFXEcho(iface);
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IDirectSoundFXEcho))
+ {
+ *ppv = &This->IDirectSoundFXEcho_iface;
+ }
+ else if(IsEqualGUID(riid, &IID_IMediaObject))
+ {
+ *ppv = &This->IMediaObject_iface;
+ }
+ else if(IsEqualGUID(riid, &IID_IMediaObjectInPlace))
+ {
+ *ppv = &This->IMediaObjectInPlace_iface;
+ }
+
+ if(!*ppv)
+ {
+ FIXME("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppv);
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+
+ return S_OK;
+}
+
+static ULONG WINAPI echofx_AddRef(IDirectSoundFXEcho *iface)
+{
+ struct dmo_echofx *This = impl_from_IDirectSoundFXEcho(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%u\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI echofx_Release(IDirectSoundFXEcho *iface)
+{
+ struct dmo_echofx *This = impl_from_IDirectSoundFXEcho(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%u\n", This, ref);
+
+ if (!ref)
+ {
+ heap_free(This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI echofx_SetAllParameters(IDirectSoundFXEcho *iface, const DSFXEcho *echo)
+{
+ struct dmo_echofx *This = impl_from_IDirectSoundFXEcho(iface);
+ FIXME("(%p) %p\n", This, echo);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI echofx_GetAllParameters(IDirectSoundFXEcho *iface, DSFXEcho *echo)
+{
+ struct dmo_echofx *This = impl_from_IDirectSoundFXEcho(iface);
+ FIXME("(%p) %p\n", This, echo);
+
+ return E_NOTIMPL;
+}
+
+static const struct IDirectSoundFXEchoVtbl echofxVtbl =
+{
+ echofx_QueryInterface,
+ echofx_AddRef,
+ echofx_Release,
+ echofx_SetAllParameters,
+ echofx_GetAllParameters
+};
+
+HRESULT WINAPI EchoFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
+{
+ struct dmo_echofx *object;
+ HRESULT ret;
+
+ TRACE("(%p, %s, %p)\n", outer, debugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+ if (!object)
+ return E_OUTOFMEMORY;
+
+ object->IDirectSoundFXEcho_iface.lpVtbl = &echofxVtbl;
+ object->IMediaObject_iface.lpVtbl = &echo_mediaobjectVtbl;
+ object->IMediaObjectInPlace_iface.lpVtbl = &echo_mediainplaceVtbl;
+ object->ref = 1;
+
+ ret = echofx_QueryInterface(&object->IDirectSoundFXEcho_iface, riid, ppv);
+ echofx_Release(&object->IDirectSoundFXEcho_iface);
+
+ return ret;
+}
diff --git a/dlls/dsdmo/main.c b/dlls/dsdmo/main.c
index 61a67f44d8..d751f90dc9 100644
--- a/dlls/dsdmo/main.c
+++ b/dlls/dsdmo/main.c
@@ -17,10 +17,12 @@
*/
#define COBJMACROS
+#include "windows.h"
#include "ole2.h"
#include "rpcproxy.h"
-#include "wine/debug.h"
+#include "initguid.h"
+#include "dsdmo_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsdmo);
@@ -49,11 +51,64 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
return TRUE;
}
+static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
+{
+ *ppv = NULL;
+
+ if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) {
+ *ppv = iface;
+ }
+
+ if(*ppv) {
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+ }
+
+ WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
+{
+ TRACE("(%p)\n", iface);
+ return 2;
+}
+
+static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
+{
+ TRACE("(%p)\n", iface);
+ return 1;
+}
+
+static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
+{
+ TRACE("(%p)->(%x)\n", iface, fLock);
+ return S_OK;
+}
+
+static const IClassFactoryVtbl EchoFactoryVtbl = {
+ ClassFactory_QueryInterface,
+ ClassFactory_AddRef,
+ ClassFactory_Release,
+ EchoFactory_CreateInstance,
+ ClassFactory_LockServer
+};
+
+static IClassFactory echofx_factory = { &EchoFactoryVtbl };
+
/***********************************************************************
* DllGetClassObject
*/
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
+ TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+
+ if(IsEqualGUID(&GUID_DSFX_STANDARD_ECHO, rclsid))
+ {
+ TRACE("GUID_DSFX_STANDARD_ECHO\n");
+ return IClassFactory_QueryInterface(&echofx_factory, riid, ppv);
+ }
+
FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return CLASS_E_CLASSNOTAVAILABLE;
}
--
2.17.1