Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
December 2019
- 73 participants
- 1394 messages
Re: [PATCH 1/5] msado15: Add typelib.
by Nikolay Sivov
Why does it need explicit calling convention for methods?
Dec. 6, 2019
[PATCH 5/5] msado15: Implement _Stream_put_Type and _Stream_get_Type.
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
configure.ac | 1 +
dlls/msado15/stream.c | 20 +++++++----
dlls/msado15/tests/Makefile.in | 5 +++
dlls/msado15/tests/msado15.c | 63 ++++++++++++++++++++++++++++++++++
4 files changed, 83 insertions(+), 6 deletions(-)
create mode 100644 dlls/msado15/tests/Makefile.in
create mode 100644 dlls/msado15/tests/msado15.c
diff --git a/configure.ac b/configure.ac
index 06ac9c6c71..b0ba094134 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3439,6 +3439,7 @@ WINE_CONFIG_MAKEFILE(dlls/msacm32.drv)
WINE_CONFIG_MAKEFILE(dlls/msacm32)
WINE_CONFIG_MAKEFILE(dlls/msacm32/tests)
WINE_CONFIG_MAKEFILE(dlls/msado15)
+WINE_CONFIG_MAKEFILE(dlls/msado15/tests)
WINE_CONFIG_MAKEFILE(dlls/msadp32.acm)
WINE_CONFIG_MAKEFILE(dlls/msasn1)
WINE_CONFIG_MAKEFILE(dlls/mscat32)
diff --git a/dlls/msado15/stream.c b/dlls/msado15/stream.c
index 48a485d599..8e88b9aa65 100644
--- a/dlls/msado15/stream.c
+++ b/dlls/msado15/stream.c
@@ -32,8 +32,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(msado15);
struct stream
{
- _Stream Stream_iface;
- LONG refs;
+ _Stream Stream_iface;
+ LONG refs;
+ StreamTypeEnum type;
};
static inline struct stream *impl_from_Stream( _Stream *iface )
@@ -130,14 +131,20 @@ static HRESULT WINAPI stream_put_Position( _Stream *iface, LONG pos )
static HRESULT WINAPI stream_get_Type( _Stream *iface, StreamTypeEnum *type )
{
- FIXME( "%p, %p\n", iface, type );
- return E_NOTIMPL;
+ struct stream *stream = impl_from_Stream( iface );
+ TRACE( "%p, %p\n", stream, type );
+
+ *type = stream->type;
+ return S_OK;
}
static HRESULT WINAPI stream_put_Type( _Stream *iface, StreamTypeEnum type )
{
- FIXME( "%p, %u\n", iface, type );
- return E_NOTIMPL;
+ struct stream *stream = impl_from_Stream( iface );
+ TRACE( "%p, %u\n", stream, type );
+
+ stream->type = type;
+ return S_OK;
}
static HRESULT WINAPI stream_get_LineSeparator( _Stream *iface, LineSeparatorEnum *sep )
@@ -305,6 +312,7 @@ HRESULT Stream_create( void **obj )
if (!(stream = heap_alloc_zero( sizeof(*stream) ))) return E_OUTOFMEMORY;
stream->Stream_iface.lpVtbl = &stream_vtbl;
stream->refs = 1;
+ stream->type = adTypeText;
*obj = &stream->Stream_iface;
TRACE( "returning iface %p\n", *obj );
diff --git a/dlls/msado15/tests/Makefile.in b/dlls/msado15/tests/Makefile.in
new file mode 100644
index 0000000000..a97f3dd433
--- /dev/null
+++ b/dlls/msado15/tests/Makefile.in
@@ -0,0 +1,5 @@
+TESTDLL = msado15.dll
+IMPORTS = oleaut32 ole32
+
+C_SRCS = \
+ msado15.c
diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c
new file mode 100644
index 0000000000..ed465e2072
--- /dev/null
+++ b/dlls/msado15/tests/msado15.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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 <stdio.h>
+#define COBJMACROS
+#include <initguid.h>
+#include <oledb.h>
+#include <msado15_backcompat.h>
+#include "wine/test.h"
+
+static void test_Stream(void)
+{
+ _Stream *stream;
+ StreamTypeEnum type;
+ LONG refs;
+ HRESULT hr;
+
+ hr = CoCreateInstance( &CLSID_Stream, NULL, CLSCTX_INPROC_SERVER, &IID__Stream, (void **)&stream );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ /* check default type */
+ type = 0;
+ hr = _Stream_get_Type( stream, &type );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( type == adTypeText, "got %u\n", type );
+
+ hr = _Stream_put_Type( stream, adTypeBinary );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ type = 0;
+ hr = _Stream_get_Type( stream, &type );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( type == adTypeBinary, "got %u\n", type );
+
+ /* revert */
+ hr = _Stream_put_Type( stream, adTypeText );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ refs = _Stream_Release( stream );
+ ok( !refs, "got %d\n", refs );
+}
+
+START_TEST(msado15)
+{
+ CoInitialize( NULL );
+ test_Stream();
+ CoUninitialize();
+}
--
2.20.1
Dec. 6, 2019
[PATCH 4/5] msado15: Add a stub _Stream implementation.
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/msado15/Makefile.in | 3 +-
dlls/msado15/main.c | 5 +
dlls/msado15/msado15_classes.idl | 8 +
dlls/msado15/msado15_private.h | 1 +
dlls/msado15/stream.c | 312 +++++++++++++++++++++++++++++++
5 files changed, 328 insertions(+), 1 deletion(-)
create mode 100644 dlls/msado15/stream.c
diff --git a/dlls/msado15/Makefile.in b/dlls/msado15/Makefile.in
index 5b255df323..604f9ff018 100644
--- a/dlls/msado15/Makefile.in
+++ b/dlls/msado15/Makefile.in
@@ -6,7 +6,8 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
connection.c \
main.c \
- recordset.c
+ recordset.c \
+ stream.c
IDL_SRCS = \
msado15_classes.idl \
diff --git a/dlls/msado15/main.c b/dlls/msado15/main.c
index 321ba40e3b..32ae252337 100644
--- a/dlls/msado15/main.c
+++ b/dlls/msado15/main.c
@@ -119,6 +119,7 @@ static const struct IClassFactoryVtbl msadocf_vtbl =
static struct msadocf connection_cf = { { &msadocf_vtbl }, Connection_create };
static struct msadocf recordset_cf = { { &msadocf_vtbl }, Recordset_create };
+static struct msadocf stream_cf = { { &msadocf_vtbl }, Stream_create };
/***********************************************************************
* DllGetClassObject
@@ -137,6 +138,10 @@ HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID iid, void **obj )
{
cf = &recordset_cf.IClassFactory_iface;
}
+ else if (IsEqualGUID( clsid, &CLSID_Stream ))
+ {
+ cf = &stream_cf.IClassFactory_iface;
+ }
if (!cf) return CLASS_E_CLASSNOTAVAILABLE;
return IClassFactory_QueryInterface( cf, iid, obj );
}
diff --git a/dlls/msado15/msado15_classes.idl b/dlls/msado15/msado15_classes.idl
index 56e86a0dc6..5ede180240 100644
--- a/dlls/msado15/msado15_classes.idl
+++ b/dlls/msado15/msado15_classes.idl
@@ -33,3 +33,11 @@ coclass Connection { interface _Connection; }
uuid(00000535-0000-0010-8000-00aa006d2ea4)
]
coclass Recordset { interface _Recordset; }
+
+[
+ threading(both),
+ progid("ADODB.Stream.6.0"),
+ vi_progid("ADODB.Stream"),
+ uuid(00000566-0000-0010-8000-00aa006d2ea4)
+]
+coclass Stream { interface _Stream; }
diff --git a/dlls/msado15/msado15_private.h b/dlls/msado15/msado15_private.h
index 1f8948522b..83c8b7c966 100644
--- a/dlls/msado15/msado15_private.h
+++ b/dlls/msado15/msado15_private.h
@@ -21,5 +21,6 @@
HRESULT Connection_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Recordset_create( void ** ) DECLSPEC_HIDDEN;
+HRESULT Stream_create( void ** ) DECLSPEC_HIDDEN;
#endif /* _WINE_MSADO15_PRIVATE_H_ */
diff --git a/dlls/msado15/stream.c b/dlls/msado15/stream.c
new file mode 100644
index 0000000000..48a485d599
--- /dev/null
+++ b/dlls/msado15/stream.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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 <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#define COBJMACROS
+#include "objbase.h"
+#include "msado15_backcompat.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+#include "msado15_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msado15);
+
+struct stream
+{
+ _Stream Stream_iface;
+ LONG refs;
+};
+
+static inline struct stream *impl_from_Stream( _Stream *iface )
+{
+ return CONTAINING_RECORD( iface, struct stream, Stream_iface );
+}
+
+static ULONG WINAPI stream_AddRef( _Stream *iface )
+{
+ struct stream *stream = impl_from_Stream( iface );
+ return InterlockedIncrement( &stream->refs );
+}
+
+static ULONG WINAPI stream_Release( _Stream *iface )
+{
+ struct stream *stream = impl_from_Stream( iface );
+ LONG refs = InterlockedDecrement( &stream->refs );
+ if (!refs)
+ {
+ TRACE( "destroying %p\n", stream );
+ heap_free( stream );
+ }
+ return refs;
+}
+
+static HRESULT WINAPI stream_QueryInterface( _Stream *iface, REFIID riid, void **obj )
+{
+ TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
+
+ if (IsEqualGUID( riid, &IID__Stream ) || IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ))
+ {
+ *obj = iface;
+ }
+ else
+ {
+ FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
+ return E_NOINTERFACE;
+ }
+ stream_AddRef( iface );
+ return S_OK;
+}
+
+static HRESULT WINAPI stream_GetTypeInfoCount( _Stream *iface, UINT *count )
+{
+ FIXME( "%p, %p\n", iface, count );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_GetTypeInfo( _Stream *iface, UINT index, LCID lcid, ITypeInfo **info )
+{
+ FIXME( "%p, %u, %u, %p\n", iface, index, lcid, info );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_GetIDsOfNames( _Stream *iface, REFIID riid, LPOLESTR *names, UINT count,
+ LCID lcid, DISPID *dispid )
+{
+ FIXME( "%p, %s, %p, %u, %u, %p\n", iface, debugstr_guid(riid), names, count, lcid, dispid );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Invoke( _Stream *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
+ DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
+{
+ FIXME( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", iface, member, debugstr_guid(riid), lcid, flags, params,
+ result, excep_info, arg_err );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_get_Size( _Stream *iface, LONG *size )
+{
+ FIXME( "%p, %p\n", iface, size );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_get_EOS( _Stream *iface, VARIANT_BOOL *eos )
+{
+ FIXME( "%p, %p\n", iface, eos );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_get_Position( _Stream *iface, LONG *pos )
+{
+ FIXME( "%p, %p\n", iface, pos );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_put_Position( _Stream *iface, LONG pos )
+{
+ FIXME( "%p, %d\n", iface, pos );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_get_Type( _Stream *iface, StreamTypeEnum *type )
+{
+ FIXME( "%p, %p\n", iface, type );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_put_Type( _Stream *iface, StreamTypeEnum type )
+{
+ FIXME( "%p, %u\n", iface, type );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_get_LineSeparator( _Stream *iface, LineSeparatorEnum *sep )
+{
+ FIXME( "%p, %p\n", iface, sep );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_put_LineSeparator( _Stream *iface, LineSeparatorEnum sep )
+{
+ FIXME( "%p, %d\n", iface, sep );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_get_State( _Stream *iface, ObjectStateEnum *state )
+{
+ FIXME( "%p, %p\n", iface, state );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_get_Mode( _Stream *iface, ConnectModeEnum *mode )
+{
+ FIXME( "%p, %p\n", iface, mode );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_put_Mode( _Stream *iface, ConnectModeEnum mode )
+{
+ FIXME( "%p, %u\n", iface, mode );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_get_Charset( _Stream *iface, BSTR *charset )
+{
+ FIXME( "%p, %p\n", iface, charset );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_put_Charset( _Stream *iface, BSTR charset )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(charset) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Read( _Stream *iface, LONG size, VARIANT *val )
+{
+ FIXME( "%p, %d, %p\n", iface, size, val );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Open( _Stream *iface, VARIANT src, ConnectModeEnum mode, StreamOpenOptionsEnum options,
+ BSTR username, BSTR password )
+{
+ FIXME( "%p, %s, %u, %d, %s, %p\n", iface, debugstr_variant(&src), mode, options, debugstr_w(username), password );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Close( _Stream *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_SkipLine( _Stream *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Write( _Stream *iface, VARIANT buf )
+{
+ FIXME( "%p, %s\n", iface, debugstr_variant(&buf) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_SetEOS( _Stream *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_CopyTo( _Stream *iface, _Stream *dst, LONG size )
+{
+ FIXME( "%p, %p, %d\n", iface, dst, size );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Flush( _Stream *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_SaveToFile( _Stream *iface, BSTR filename, SaveOptionsEnum options )
+{
+ FIXME( "%p, %s, %u\n", iface, debugstr_w(filename), options );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_LoadFromFile( _Stream *iface, BSTR filename )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(filename) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_ReadText( _Stream *iface, LONG len, BSTR *ret )
+{
+ FIXME( "%p, %d, %p\n", iface, len, ret );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_WriteText( _Stream *iface, BSTR data, StreamWriteEnum options )
+{
+ FIXME( "%p, %p, %u\n", iface, debugstr_w(data), options );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stream_Cancel( _Stream *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static const struct _StreamVtbl stream_vtbl =
+{
+ stream_QueryInterface,
+ stream_AddRef,
+ stream_Release,
+ stream_GetTypeInfoCount,
+ stream_GetTypeInfo,
+ stream_GetIDsOfNames,
+ stream_Invoke,
+ stream_get_Size,
+ stream_get_EOS,
+ stream_get_Position,
+ stream_put_Position,
+ stream_get_Type,
+ stream_put_Type,
+ stream_get_LineSeparator,
+ stream_put_LineSeparator,
+ stream_get_State,
+ stream_get_Mode,
+ stream_put_Mode,
+ stream_get_Charset,
+ stream_put_Charset,
+ stream_Read,
+ stream_Open,
+ stream_Close,
+ stream_SkipLine,
+ stream_Write,
+ stream_SetEOS,
+ stream_CopyTo,
+ stream_Flush,
+ stream_SaveToFile,
+ stream_LoadFromFile,
+ stream_ReadText,
+ stream_WriteText,
+ stream_Cancel
+};
+
+HRESULT Stream_create( void **obj )
+{
+ struct stream *stream;
+
+ if (!(stream = heap_alloc_zero( sizeof(*stream) ))) return E_OUTOFMEMORY;
+ stream->Stream_iface.lpVtbl = &stream_vtbl;
+ stream->refs = 1;
+
+ *obj = &stream->Stream_iface;
+ TRACE( "returning iface %p\n", *obj );
+ return S_OK;
+}
--
2.20.1
Dec. 6, 2019
[PATCH 3/5] msado15: Add a stub _Recordset implementation.
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/msado15/Makefile.in | 3 +-
dlls/msado15/main.c | 5 +
dlls/msado15/msado15_classes.idl | 8 +
dlls/msado15/msado15_private.h | 1 +
dlls/msado15/recordset.c | 686 +++++++++++++++++++++++++++++++
5 files changed, 702 insertions(+), 1 deletion(-)
create mode 100644 dlls/msado15/recordset.c
diff --git a/dlls/msado15/Makefile.in b/dlls/msado15/Makefile.in
index b901944bc1..5b255df323 100644
--- a/dlls/msado15/Makefile.in
+++ b/dlls/msado15/Makefile.in
@@ -5,7 +5,8 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
connection.c \
- main.c
+ main.c \
+ recordset.c
IDL_SRCS = \
msado15_classes.idl \
diff --git a/dlls/msado15/main.c b/dlls/msado15/main.c
index d292826b1f..321ba40e3b 100644
--- a/dlls/msado15/main.c
+++ b/dlls/msado15/main.c
@@ -118,6 +118,7 @@ static const struct IClassFactoryVtbl msadocf_vtbl =
};
static struct msadocf connection_cf = { { &msadocf_vtbl }, Connection_create };
+static struct msadocf recordset_cf = { { &msadocf_vtbl }, Recordset_create };
/***********************************************************************
* DllGetClassObject
@@ -132,6 +133,10 @@ HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID iid, void **obj )
{
cf = &connection_cf.IClassFactory_iface;
}
+ else if (IsEqualGUID( clsid, &CLSID_Recordset ))
+ {
+ cf = &recordset_cf.IClassFactory_iface;
+ }
if (!cf) return CLASS_E_CLASSNOTAVAILABLE;
return IClassFactory_QueryInterface( cf, iid, obj );
}
diff --git a/dlls/msado15/msado15_classes.idl b/dlls/msado15/msado15_classes.idl
index f69fea0a1a..56e86a0dc6 100644
--- a/dlls/msado15/msado15_classes.idl
+++ b/dlls/msado15/msado15_classes.idl
@@ -25,3 +25,11 @@
uuid(00000514-0000-0010-8000-00aa006d2ea4)
]
coclass Connection { interface _Connection; }
+
+[
+ threading(both),
+ progid("ADODB.Recordset.6.0"),
+ vi_progid("ADODB.Recordset"),
+ uuid(00000535-0000-0010-8000-00aa006d2ea4)
+]
+coclass Recordset { interface _Recordset; }
diff --git a/dlls/msado15/msado15_private.h b/dlls/msado15/msado15_private.h
index 1d4c379443..1f8948522b 100644
--- a/dlls/msado15/msado15_private.h
+++ b/dlls/msado15/msado15_private.h
@@ -20,5 +20,6 @@
#define _WINE_MSADO15_PRIVATE_H_
HRESULT Connection_create( void ** ) DECLSPEC_HIDDEN;
+HRESULT Recordset_create( void ** ) DECLSPEC_HIDDEN;
#endif /* _WINE_MSADO15_PRIVATE_H_ */
diff --git a/dlls/msado15/recordset.c b/dlls/msado15/recordset.c
new file mode 100644
index 0000000000..bf0ca6e90f
--- /dev/null
+++ b/dlls/msado15/recordset.c
@@ -0,0 +1,686 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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 <stdarg.h>
+#include <assert.h>
+#include "windef.h"
+#include "winbase.h"
+#define COBJMACROS
+#include "objbase.h"
+#include "msado15_backcompat.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+#include "msado15_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msado15);
+
+struct recordset
+{
+ _Recordset Recordset_iface;
+ LONG refs;
+};
+
+static inline struct recordset *impl_from_Recordset( _Recordset *iface )
+{
+ return CONTAINING_RECORD( iface, struct recordset, Recordset_iface );
+}
+
+static ULONG WINAPI recordset_AddRef( _Recordset *iface )
+{
+ struct recordset *recordset = impl_from_Recordset( iface );
+ LONG refs = InterlockedIncrement( &recordset->refs );
+ TRACE( "%p new refcount %d\n", recordset, refs );
+ return refs;
+}
+
+static ULONG WINAPI recordset_Release( _Recordset *iface )
+{
+ struct recordset *recordset = impl_from_Recordset( iface );
+ LONG refs = InterlockedDecrement( &recordset->refs );
+ TRACE( "%p new refcount %d\n", recordset, refs );
+ if (!refs)
+ {
+ TRACE( "destroying %p\n", recordset );
+ heap_free( recordset );
+ }
+ return refs;
+}
+
+static HRESULT WINAPI recordset_QueryInterface( _Recordset *iface, REFIID riid, void **obj )
+{
+ TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
+
+ if (IsEqualGUID( riid, &IID__Recordset ) || IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ))
+ {
+ *obj = iface;
+ }
+ else
+ {
+ FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
+ return E_NOINTERFACE;
+ }
+ recordset_AddRef( iface );
+ return S_OK;
+}
+
+static HRESULT WINAPI recordset_GetTypeInfoCount( _Recordset *iface, UINT *count )
+{
+ FIXME( "%p, %p\n", iface, count );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_GetTypeInfo( _Recordset *iface, UINT index, LCID lcid, ITypeInfo **info )
+{
+ FIXME( "%p, %u, %u, %p\n", iface, index, lcid, info );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_GetIDsOfNames( _Recordset *iface, REFIID riid, LPOLESTR *names, UINT count,
+ LCID lcid, DISPID *dispid )
+{
+ FIXME( "%p, %s, %p, %u, %u, %p\n", iface, debugstr_guid(riid), names, count, lcid, dispid );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Invoke( _Recordset *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
+ DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
+{
+ FIXME( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", iface, member, debugstr_guid(riid), lcid, flags, params,
+ result, excep_info, arg_err );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Properties( _Recordset *iface, Properties **obj )
+{
+ FIXME( "%p, %p\n", iface, obj );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_AbsolutePosition( _Recordset *iface, PositionEnum_Param *pos )
+{
+ FIXME( "%p, %p\n", iface, pos );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_AbsolutePosition( _Recordset *iface, PositionEnum_Param pos )
+{
+ FIXME( "%p, %d\n", iface, pos );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_putref_ActiveConnection( _Recordset *iface, IDispatch *connection )
+{
+ FIXME( "%p, %p\n", iface, connection );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_ActiveConnection( _Recordset *iface, VARIANT connection )
+{
+ FIXME( "%p, %s\n", iface, debugstr_variant(&connection) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_ActiveConnection( _Recordset *iface, VARIANT *connection )
+{
+ FIXME( "%p, %p\n", iface, connection );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_BOF( _Recordset *iface, VARIANT_BOOL *bof )
+{
+ FIXME( "%p, %p\n", iface, bof );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Bookmark( _Recordset *iface, VARIANT *bookmark )
+{
+ FIXME( "%p, %p\n", iface, bookmark );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_Bookmark( _Recordset *iface, VARIANT bookmark )
+{
+ FIXME( "%p, %s\n", iface, debugstr_variant(&bookmark) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_CacheSize( _Recordset *iface, LONG *size )
+{
+ FIXME( "%p, %p\n", iface, size );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_CacheSize( _Recordset *iface, LONG size )
+{
+ FIXME( "%p, %d\n", iface, size );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_CursorType( _Recordset *iface, CursorTypeEnum *cursor_type )
+{
+ FIXME( "%p, %p\n", iface, cursor_type );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_CursorType( _Recordset *iface, CursorTypeEnum cursor_type )
+{
+ FIXME( "%p, %d\n", iface, cursor_type );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_EOF( _Recordset *iface, VARIANT_BOOL *eof )
+{
+ FIXME( "%p, %p\n", iface, eof );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Fields( _Recordset *iface, Fields **obj )
+{
+ FIXME( "%p, %p\n", iface, obj );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_LockType( _Recordset *iface, LockTypeEnum *lock_type )
+{
+ FIXME( "%p, %p\n", iface, lock_type );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_LockType( _Recordset *iface, LockTypeEnum lock_type )
+{
+ FIXME( "%p, %d\n", iface, lock_type );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_MaxRecords( _Recordset *iface, LONG *max_records )
+{
+ FIXME( "%p, %p\n", iface, max_records );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_MaxRecords( _Recordset *iface, LONG max_records )
+{
+ FIXME( "%p, %d\n", iface, max_records );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_RecordCount( _Recordset *iface, LONG *count )
+{
+ FIXME( "%p, %p\n", iface, count );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_putref_Source( _Recordset *iface, IDispatch *source )
+{
+ FIXME( "%p, %p\n", iface, source );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_Source( _Recordset *iface, BSTR source )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(source) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Source( _Recordset *iface, VARIANT *source )
+{
+ FIXME( "%p, %p\n", iface, source );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_AddNew( _Recordset *iface, VARIANT field_list, VARIANT values )
+{
+ FIXME( "%p, %s, %s\n", iface, debugstr_variant(&field_list), debugstr_variant(&values) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_CancelUpdate( _Recordset *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Close( _Recordset *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Delete( _Recordset *iface, AffectEnum affect_records )
+{
+ FIXME( "%p, %u\n", iface, affect_records );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_GetRows( _Recordset *iface, LONG rows, VARIANT start, VARIANT fields, VARIANT *var )
+{
+ FIXME( "%p, %d, %s, %s, %p\n", iface, rows, debugstr_variant(&start), debugstr_variant(&fields), var );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Move( _Recordset *iface, LONG num_records, VARIANT start )
+{
+ FIXME( "%p, %d, %s\n", iface, num_records, debugstr_variant(&start) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_MoveNext( _Recordset *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_MovePrevious( _Recordset *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_MoveFirst( _Recordset *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_MoveLast( _Recordset *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Open( _Recordset *iface, VARIANT source, VARIANT active_connection,
+ CursorTypeEnum cursor_type, LockTypeEnum lock_type, LONG options )
+{
+ FIXME( "%p, %s, %s, %d, %d, %d\n", iface, debugstr_variant(&source), debugstr_variant(&active_connection),
+ cursor_type, lock_type, options );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Requery( _Recordset *iface, LONG options )
+{
+ FIXME( "%p, %d\n", iface, options );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset__xResync( _Recordset *iface, AffectEnum affect_records )
+{
+ FIXME( "%p, %u\n", iface, affect_records );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Update( _Recordset *iface, VARIANT fields, VARIANT values )
+{
+ FIXME( "%p, %s, %s\n", iface, debugstr_variant(&fields), debugstr_variant(&values) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_AbsolutePage( _Recordset *iface, PositionEnum_Param *pos )
+{
+ FIXME( "%p, %p\n", iface, pos );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_AbsolutePage( _Recordset *iface, PositionEnum_Param pos )
+{
+ FIXME( "%p, %d\n", iface, pos );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_EditMode( _Recordset *iface, EditModeEnum *mode )
+{
+ FIXME( "%p, %p\n", iface, mode );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Filter( _Recordset *iface, VARIANT *criteria )
+{
+ FIXME( "%p, %p\n", iface, criteria );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_Filter( _Recordset *iface, VARIANT criteria )
+{
+ FIXME( "%p, %s\n", iface, debugstr_variant(&criteria) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_PageCount( _Recordset *iface, LONG *count )
+{
+ FIXME( "%p, %p\n", iface, count );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_PageSize( _Recordset *iface, LONG *size )
+{
+ FIXME( "%p, %p\n", iface, size );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_PageSize( _Recordset *iface, LONG size )
+{
+ FIXME( "%p, %d\n", iface, size );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Sort( _Recordset *iface, BSTR *criteria )
+{
+ FIXME( "%p, %p\n", iface, criteria );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_Sort( _Recordset *iface, BSTR criteria )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(criteria) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Status( _Recordset *iface, LONG *status )
+{
+ FIXME( "%p, %p\n", iface, status );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_State( _Recordset *iface, LONG *state )
+{
+ FIXME( "%p, %p\n", iface, state );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset__xClone( _Recordset *iface, _Recordset **obj )
+{
+ FIXME( "%p, %p\n", iface, obj );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_UpdateBatch( _Recordset *iface, AffectEnum affect_records )
+{
+ FIXME( "%p, %u\n", iface, affect_records );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_CancelBatch( _Recordset *iface, AffectEnum affect_records )
+{
+ FIXME( "%p, %u\n", iface, affect_records );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_CursorLocation( _Recordset *iface, CursorLocationEnum *cursor_loc )
+{
+ FIXME( "%p, %p\n", iface, cursor_loc );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_CursorLocation( _Recordset *iface, CursorLocationEnum cursor_loc )
+{
+ FIXME( "%p, %u\n", iface, cursor_loc );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_NextRecordset( _Recordset *iface, VARIANT *records_affected, _Recordset **record_set )
+{
+ FIXME( "%p, %p, %p\n", iface, records_affected, record_set );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Supports( _Recordset *iface, CursorOptionEnum cursor_options, VARIANT_BOOL *ret )
+{
+ FIXME( "%p, %08x, %p\n", iface, cursor_options, ret );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Collect( _Recordset *iface, VARIANT index, VARIANT *var )
+{
+ FIXME( "%p, %s, %p\n", iface, debugstr_variant(&index), var );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_Collect( _Recordset *iface, VARIANT index, VARIANT var )
+{
+ FIXME( "%p, %s, %s\n", iface, debugstr_variant(&index), debugstr_variant(&var) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_MarshalOptions( _Recordset *iface, MarshalOptionsEnum *options )
+{
+ FIXME( "%p, %p\n", iface, options );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_MarshalOptions( _Recordset *iface, MarshalOptionsEnum options )
+{
+ FIXME( "%p, %u\n", iface, options );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Find( _Recordset *iface, BSTR criteria, LONG skip_records,
+ SearchDirectionEnum search_direction, VARIANT start )
+{
+ FIXME( "%p, %s, %d, %d, %s\n", iface, debugstr_w(criteria), skip_records, search_direction,
+ debugstr_variant(&start) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Cancel( _Recordset *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_DataSource( _Recordset *iface, IUnknown **data_source )
+{
+ FIXME( "%p, %p\n", iface, data_source );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_putref_DataSource( _Recordset *iface, IUnknown *data_source )
+{
+ FIXME( "%p, %p\n", iface, data_source );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset__xSave( _Recordset *iface, BSTR filename, PersistFormatEnum persist_format )
+{
+ FIXME( "%p, %s, %u\n", iface, debugstr_w(filename), persist_format );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_ActiveCommand( _Recordset *iface, IDispatch **cmd )
+{
+ FIXME( "%p, %p\n", iface, cmd );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_StayInSync( _Recordset *iface, VARIANT_BOOL stay_in_sync )
+{
+ FIXME( "%p, %d\n", iface, stay_in_sync );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_StayInSync( _Recordset *iface, VARIANT_BOOL *stay_in_sync )
+{
+ FIXME( "%p, %p\n", iface, stay_in_sync );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_GetString( _Recordset *iface, StringFormatEnum string_format, LONG num_rows,
+ BSTR column_delimeter, BSTR row_delimeter, BSTR null_expr,
+ BSTR *ret_string )
+{
+ FIXME( "%p, %u, %d, %s, %s, %s, %p\n", iface, string_format, num_rows, debugstr_w(column_delimeter),
+ debugstr_w(row_delimeter), debugstr_w(null_expr), ret_string );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_DataMember( _Recordset *iface, BSTR *data_member )
+{
+ FIXME( "%p, %p\n", iface, data_member );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_DataMember( _Recordset *iface, BSTR data_member )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(data_member) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_CompareBookmarks( _Recordset *iface, VARIANT bookmark1, VARIANT bookmark2, CompareEnum *compare )
+{
+ FIXME( "%p, %s, %s, %p\n", iface, debugstr_variant(&bookmark1), debugstr_variant(&bookmark2), compare );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Clone( _Recordset *iface, LockTypeEnum lock_type, _Recordset **obj )
+{
+ FIXME( "%p, %d, %p\n", iface, lock_type, obj );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Resync( _Recordset *iface, AffectEnum affect_records, ResyncEnum resync_values )
+{
+ FIXME( "%p, %u, %u\n", iface, affect_records, resync_values );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Seek( _Recordset *iface, VARIANT key_values, SeekEnum seek_option )
+{
+ FIXME( "%p, %s, %u\n", iface, debugstr_variant(&key_values), seek_option );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_put_Index( _Recordset *iface, BSTR index )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(index) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_get_Index( _Recordset *iface, BSTR *index )
+{
+ FIXME( "%p, %p\n", iface, index );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI recordset_Save( _Recordset *iface, VARIANT destination, PersistFormatEnum persist_format )
+{
+ FIXME( "%p, %s, %u\n", iface, debugstr_variant(&destination), persist_format );
+ return E_NOTIMPL;
+}
+
+static const struct _RecordsetVtbl recordset_vtbl =
+{
+ recordset_QueryInterface,
+ recordset_AddRef,
+ recordset_Release,
+ recordset_GetTypeInfoCount,
+ recordset_GetTypeInfo,
+ recordset_GetIDsOfNames,
+ recordset_Invoke,
+ recordset_get_Properties,
+ recordset_get_AbsolutePosition,
+ recordset_put_AbsolutePosition,
+ recordset_putref_ActiveConnection,
+ recordset_put_ActiveConnection,
+ recordset_get_ActiveConnection,
+ recordset_get_BOF,
+ recordset_get_Bookmark,
+ recordset_put_Bookmark,
+ recordset_get_CacheSize,
+ recordset_put_CacheSize,
+ recordset_get_CursorType,
+ recordset_put_CursorType,
+ recordset_get_EOF,
+ recordset_get_Fields,
+ recordset_get_LockType,
+ recordset_put_LockType,
+ recordset_get_MaxRecords,
+ recordset_put_MaxRecords,
+ recordset_get_RecordCount,
+ recordset_putref_Source,
+ recordset_put_Source,
+ recordset_get_Source,
+ recordset_AddNew,
+ recordset_CancelUpdate,
+ recordset_Close,
+ recordset_Delete,
+ recordset_GetRows,
+ recordset_Move,
+ recordset_MoveNext,
+ recordset_MovePrevious,
+ recordset_MoveFirst,
+ recordset_MoveLast,
+ recordset_Open,
+ recordset_Requery,
+ recordset__xResync,
+ recordset_Update,
+ recordset_get_AbsolutePage,
+ recordset_put_AbsolutePage,
+ recordset_get_EditMode,
+ recordset_get_Filter,
+ recordset_put_Filter,
+ recordset_get_PageCount,
+ recordset_get_PageSize,
+ recordset_put_PageSize,
+ recordset_get_Sort,
+ recordset_put_Sort,
+ recordset_get_Status,
+ recordset_get_State,
+ recordset__xClone,
+ recordset_UpdateBatch,
+ recordset_CancelBatch,
+ recordset_get_CursorLocation,
+ recordset_put_CursorLocation,
+ recordset_NextRecordset,
+ recordset_Supports,
+ recordset_get_Collect,
+ recordset_put_Collect,
+ recordset_get_MarshalOptions,
+ recordset_put_MarshalOptions,
+ recordset_Find,
+ recordset_Cancel,
+ recordset_get_DataSource,
+ recordset_putref_DataSource,
+ recordset__xSave,
+ recordset_get_ActiveCommand,
+ recordset_put_StayInSync,
+ recordset_get_StayInSync,
+ recordset_GetString,
+ recordset_get_DataMember,
+ recordset_put_DataMember,
+ recordset_CompareBookmarks,
+ recordset_Clone,
+ recordset_Resync,
+ recordset_Seek,
+ recordset_put_Index,
+ recordset_get_Index,
+ recordset_Save
+};
+
+HRESULT Recordset_create( void **obj )
+{
+ struct recordset *recordset;
+
+ if (!(recordset = heap_alloc_zero( sizeof(*recordset) ))) return E_OUTOFMEMORY;
+ recordset->Recordset_iface.lpVtbl = &recordset_vtbl;
+ recordset->refs = 1;
+
+ *obj = &recordset->Recordset_iface;
+ TRACE( "returning iface %p\n", *obj );
+ return S_OK;
+}
--
2.20.1
Dec. 6, 2019
[PATCH 2/5] msado15: Add a stub _Connection implementation.
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/msado15/Makefile.in | 8 +-
dlls/msado15/connection.c | 344 +++++++++++++++++++++++++++++++
dlls/msado15/main.c | 106 ++++++++++
dlls/msado15/msado15.spec | 4 +-
dlls/msado15/msado15_classes.idl | 27 +++
dlls/msado15/msado15_private.h | 24 +++
6 files changed, 509 insertions(+), 4 deletions(-)
create mode 100644 dlls/msado15/connection.c
create mode 100644 dlls/msado15/msado15_classes.idl
create mode 100644 dlls/msado15/msado15_private.h
diff --git a/dlls/msado15/Makefile.in b/dlls/msado15/Makefile.in
index 779a18df14..b901944bc1 100644
--- a/dlls/msado15/Makefile.in
+++ b/dlls/msado15/Makefile.in
@@ -1,8 +1,12 @@
MODULE = msado15.dll
+IMPORTS = oleaut32
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
- main.c \
+ connection.c \
+ main.c
-IDL_SRCS = msado15_tlb.idl
+IDL_SRCS = \
+ msado15_classes.idl \
+ msado15_tlb.idl
diff --git a/dlls/msado15/connection.c b/dlls/msado15/connection.c
new file mode 100644
index 0000000000..f33bc89a1a
--- /dev/null
+++ b/dlls/msado15/connection.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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 <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#define COBJMACROS
+#include "objbase.h"
+#include "msado15_backcompat.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+#include "msado15_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msado15);
+
+struct connection
+{
+ _Connection Connection_iface;
+ LONG refs;
+};
+
+static inline struct connection *impl_from_Connection( _Connection *iface )
+{
+ return CONTAINING_RECORD( iface, struct connection, Connection_iface );
+}
+
+static ULONG WINAPI connection_AddRef( _Connection *iface )
+{
+ struct connection *connection = impl_from_Connection( iface );
+ return InterlockedIncrement( &connection->refs );
+}
+
+static ULONG WINAPI connection_Release( _Connection *iface )
+{
+ struct connection *connection = impl_from_Connection( iface );
+ LONG refs = InterlockedDecrement( &connection->refs );
+ if (!refs)
+ {
+ TRACE( "destroying %p\n", connection );
+ heap_free( connection );
+ }
+ return refs;
+}
+
+static HRESULT WINAPI connection_QueryInterface( _Connection *iface, REFIID riid, void **obj )
+{
+ TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
+
+ if (IsEqualGUID( riid, &IID__Connection ) || IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ))
+ {
+ *obj = iface;
+ }
+ else
+ {
+ FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
+ return E_NOINTERFACE;
+ }
+ connection_AddRef( iface );
+ return S_OK;
+}
+
+static HRESULT WINAPI connection_GetTypeInfoCount( _Connection *iface, UINT *count )
+{
+ FIXME( "%p, %p\n", iface, count );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_GetTypeInfo( _Connection *iface, UINT index, LCID lcid, ITypeInfo **info )
+{
+ FIXME( "%p, %u, %u, %p\n", iface, index, lcid, info );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_GetIDsOfNames( _Connection *iface, REFIID riid, LPOLESTR *names, UINT count,
+ LCID lcid, DISPID *dispid )
+{
+ FIXME( "%p, %s, %p, %u, %u, %p\n", iface, debugstr_guid(riid), names, count, lcid, dispid );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_Invoke( _Connection *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
+ DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
+{
+ FIXME( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", iface, member, debugstr_guid(riid), lcid, flags, params,
+ result, excep_info, arg_err );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_Properties( _Connection *iface, Properties **obj )
+{
+ FIXME( "%p, %p\n", iface, obj );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_ConnectionString( _Connection *iface, BSTR *str )
+{
+ FIXME( "%p, %p\n", iface, str );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_ConnectionString( _Connection *iface, BSTR str )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(str) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_CommandTimeout( _Connection *iface, LONG *timeout )
+{
+ FIXME( "%p, %p\n", iface, timeout );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_CommandTimeout( _Connection *iface, LONG timeout )
+{
+ FIXME( "%p, %d\n", iface, timeout );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_ConnectionTimeout( _Connection *iface, LONG *timeout )
+{
+ FIXME( "%p, %p\n", iface, timeout );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_ConnectionTimeout( _Connection *iface, LONG timeout )
+{
+ FIXME( "%p, %d\n", iface, timeout );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_Version( _Connection *iface, BSTR *str )
+{
+ FIXME( "%p, %p\n", iface, str );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_Close( _Connection *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_Execute( _Connection *iface, BSTR command, VARIANT *records_affected,
+ LONG options, _Recordset **record_set )
+{
+ FIXME( "%p, %s, %p, %08x, %p\n", iface, debugstr_w(command), records_affected, options, record_set );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_BeginTrans( _Connection *iface, LONG *transaction_level )
+{
+ FIXME( "%p, %p\n", iface, transaction_level );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_CommitTrans( _Connection *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_RollbackTrans( _Connection *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_Open( _Connection *iface, BSTR connect_str, BSTR userid, BSTR password,
+ LONG options )
+{
+ FIXME( "%p, %s, %s, %p, %08x\n", iface, debugstr_w(connect_str), debugstr_w(userid),
+ debugstr_w(password), options );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_Errors( _Connection *iface, Errors **obj )
+{
+ FIXME( "%p, %p\n", iface, obj );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_DefaultDatabase( _Connection *iface, BSTR *str )
+{
+ FIXME( "%p, %p\n", iface, str );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_DefaultDatabase( _Connection *iface, BSTR str )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(str) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_IsolationLevel( _Connection *iface, IsolationLevelEnum *level )
+{
+ FIXME( "%p, %p\n", iface, level );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_IsolationLevel( _Connection *iface, IsolationLevelEnum level )
+{
+ FIXME( "%p, %d\n", iface, level );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_Attributes( _Connection *iface, LONG *attr )
+{
+ FIXME( "%p, %p\n", iface, attr );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_Attributes( _Connection *iface, LONG attr )
+{
+ FIXME( "%p, %d\n", iface, attr );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_CursorLocation( _Connection *iface, CursorLocationEnum *cursor_loc )
+{
+ FIXME( "%p, %p\n", iface, cursor_loc );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_CursorLocation( _Connection *iface, CursorLocationEnum cursor_loc )
+{
+ FIXME( "%p, %u\n", iface, cursor_loc );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_Mode( _Connection *iface, ConnectModeEnum *mode )
+{
+ FIXME( "%p, %p\n", iface, mode );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_Mode( _Connection *iface, ConnectModeEnum mode )
+{
+ FIXME( "%p, %u\n", iface, mode );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_Provider( _Connection *iface, BSTR *str )
+{
+ FIXME( "%p, %p\n", iface, str );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_put_Provider( _Connection *iface, BSTR str )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(str) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_get_State( _Connection *iface, LONG *state )
+{
+ FIXME( "%p, %p\n", iface, state );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_OpenSchema( _Connection *iface, SchemaEnum schema, VARIANT restrictions,
+ VARIANT schema_id, _Recordset **record_set )
+{
+ FIXME( "%p, %d, %s, %s, %p\n", iface, schema, debugstr_variant(&restrictions),
+ debugstr_variant(&schema_id), record_set );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI connection_Cancel( _Connection *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static const struct _ConnectionVtbl connection_vtbl =
+{
+ connection_QueryInterface,
+ connection_AddRef,
+ connection_Release,
+ connection_GetTypeInfoCount,
+ connection_GetTypeInfo,
+ connection_GetIDsOfNames,
+ connection_Invoke,
+ connection_get_Properties,
+ connection_get_ConnectionString,
+ connection_put_ConnectionString,
+ connection_get_CommandTimeout,
+ connection_put_CommandTimeout,
+ connection_get_ConnectionTimeout,
+ connection_put_ConnectionTimeout,
+ connection_get_Version,
+ connection_Close,
+ connection_Execute,
+ connection_BeginTrans,
+ connection_CommitTrans,
+ connection_RollbackTrans,
+ connection_Open,
+ connection_get_Errors,
+ connection_get_DefaultDatabase,
+ connection_put_DefaultDatabase,
+ connection_get_IsolationLevel,
+ connection_put_IsolationLevel,
+ connection_get_Attributes,
+ connection_put_Attributes,
+ connection_get_CursorLocation,
+ connection_put_CursorLocation,
+ connection_get_Mode,
+ connection_put_Mode,
+ connection_get_Provider,
+ connection_put_Provider,
+ connection_get_State,
+ connection_OpenSchema,
+ connection_Cancel
+};
+
+HRESULT Connection_create( void **obj )
+{
+ struct connection *connection;
+
+ if (!(connection = heap_alloc( sizeof(*connection) ))) return E_OUTOFMEMORY;
+ connection->Connection_iface.lpVtbl = &connection_vtbl;
+ connection->refs = 1;
+
+ *obj = &connection->Connection_iface;
+ TRACE( "returning iface %p\n", *obj );
+ return S_OK;
+}
diff --git a/dlls/msado15/main.c b/dlls/msado15/main.c
index 0c5b2615d0..d292826b1f 100644
--- a/dlls/msado15/main.c
+++ b/dlls/msado15/main.c
@@ -19,10 +19,18 @@
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
+#include "initguid.h"
+#define COBJMACROS
#include "objbase.h"
#include "rpcproxy.h"
+#include "msado15_backcompat.h"
#include "wine/debug.h"
+#include "wine/heap.h"
+
+#include "msado15_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msado15);
static HINSTANCE hinstance;
@@ -38,6 +46,104 @@ BOOL WINAPI DllMain( HINSTANCE dll, DWORD reason, LPVOID reserved )
return TRUE;
}
+typedef HRESULT (*fnCreateInstance)( void **obj );
+
+struct msadocf
+{
+ IClassFactory IClassFactory_iface;
+ fnCreateInstance pfnCreateInstance;
+};
+
+static inline struct msadocf *impl_from_IClassFactory( IClassFactory *iface )
+{
+ return CONTAINING_RECORD( iface, struct msadocf, IClassFactory_iface );
+}
+
+static HRESULT WINAPI msadocf_QueryInterface( IClassFactory *iface, REFIID riid, void **obj )
+{
+ if (IsEqualGUID( riid, &IID_IUnknown ) || IsEqualGUID( riid, &IID_IClassFactory ))
+ {
+ IClassFactory_AddRef( iface );
+ *obj = iface;
+ return S_OK;
+ }
+ FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI msadocf_AddRef( IClassFactory *iface )
+{
+ return 2;
+}
+
+static ULONG WINAPI msadocf_Release( IClassFactory *iface )
+{
+ return 1;
+}
+
+static HRESULT WINAPI msadocf_CreateInstance( IClassFactory *iface, LPUNKNOWN outer, REFIID riid, void **obj )
+{
+ struct msadocf *cf = impl_from_IClassFactory( iface );
+ IUnknown *unknown;
+ HRESULT hr;
+
+ TRACE( "%p, %s, %p\n", outer, debugstr_guid(riid), obj );
+
+ *obj = NULL;
+ if (outer)
+ return CLASS_E_NOAGGREGATION;
+
+ hr = cf->pfnCreateInstance( (void **)&unknown );
+ if (FAILED(hr))
+ return hr;
+
+ hr = IUnknown_QueryInterface( unknown, riid, obj );
+ IUnknown_Release( unknown );
+ return hr;
+}
+
+static HRESULT WINAPI msadocf_LockServer( IClassFactory *iface, BOOL dolock )
+{
+ FIXME( "%p, %d\n", iface, dolock );
+ return S_OK;
+}
+
+static const struct IClassFactoryVtbl msadocf_vtbl =
+{
+ msadocf_QueryInterface,
+ msadocf_AddRef,
+ msadocf_Release,
+ msadocf_CreateInstance,
+ msadocf_LockServer
+};
+
+static struct msadocf connection_cf = { { &msadocf_vtbl }, Connection_create };
+
+/***********************************************************************
+ * DllGetClassObject
+ */
+HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID iid, void **obj )
+{
+ IClassFactory *cf = NULL;
+
+ TRACE( "%s, %s, %p\n", debugstr_guid(clsid), debugstr_guid(iid), obj );
+
+ if (IsEqualGUID( clsid, &CLSID_Connection ))
+ {
+ cf = &connection_cf.IClassFactory_iface;
+ }
+ if (!cf) return CLASS_E_CLASSNOTAVAILABLE;
+ return IClassFactory_QueryInterface( cf, iid, obj );
+}
+
+/******************************************************************
+ * DllCanUnloadNow
+ */
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+ return S_FALSE;
+}
+
/***********************************************************************
* DllRegisterServer
*/
diff --git a/dlls/msado15/msado15.spec b/dlls/msado15/msado15.spec
index 6d0e061a53..b16365d0c9 100644
--- a/dlls/msado15/msado15.spec
+++ b/dlls/msado15/msado15.spec
@@ -1,4 +1,4 @@
-@ stub DllCanUnloadNow
-@ stub DllGetClassObject
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllRegisterServer()
@ stdcall -private DllUnregisterServer()
diff --git a/dlls/msado15/msado15_classes.idl b/dlls/msado15/msado15_classes.idl
new file mode 100644
index 0000000000..f69fea0a1a
--- /dev/null
+++ b/dlls/msado15/msado15_classes.idl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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
+
+[
+ threading(apartment),
+ progid("ADODB.Connection.6.0"),
+ vi_progid("ADODB.Connection"),
+ uuid(00000514-0000-0010-8000-00aa006d2ea4)
+]
+coclass Connection { interface _Connection; }
diff --git a/dlls/msado15/msado15_private.h b/dlls/msado15/msado15_private.h
new file mode 100644
index 0000000000..1d4c379443
--- /dev/null
+++ b/dlls/msado15/msado15_private.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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_MSADO15_PRIVATE_H_
+#define _WINE_MSADO15_PRIVATE_H_
+
+HRESULT Connection_create( void ** ) DECLSPEC_HIDDEN;
+
+#endif /* _WINE_MSADO15_PRIVATE_H_ */
--
2.20.1
Dec. 6, 2019
[PATCH 1/5] msado15: Add typelib.
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
configure.ac | 1 +
dlls/msado15/Makefile.in | 8 +
dlls/msado15/main.c | 55 +
dlls/msado15/msado15.spec | 4 +
dlls/msado15/msado15_tlb.idl | 21 +
include/Makefile.in | 1 +
include/msado15_backcompat.idl | 2104 ++++++++++++++++++++++++++++++++
7 files changed, 2194 insertions(+)
create mode 100644 dlls/msado15/Makefile.in
create mode 100644 dlls/msado15/main.c
create mode 100644 dlls/msado15/msado15.spec
create mode 100644 dlls/msado15/msado15_tlb.idl
create mode 100644 include/msado15_backcompat.idl
diff --git a/configure.ac b/configure.ac
index 7f2c3cda23..06ac9c6c71 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3438,6 +3438,7 @@ WINE_CONFIG_MAKEFILE(dlls/msacm.dll16,enable_win16)
WINE_CONFIG_MAKEFILE(dlls/msacm32.drv)
WINE_CONFIG_MAKEFILE(dlls/msacm32)
WINE_CONFIG_MAKEFILE(dlls/msacm32/tests)
+WINE_CONFIG_MAKEFILE(dlls/msado15)
WINE_CONFIG_MAKEFILE(dlls/msadp32.acm)
WINE_CONFIG_MAKEFILE(dlls/msasn1)
WINE_CONFIG_MAKEFILE(dlls/mscat32)
diff --git a/dlls/msado15/Makefile.in b/dlls/msado15/Makefile.in
new file mode 100644
index 0000000000..779a18df14
--- /dev/null
+++ b/dlls/msado15/Makefile.in
@@ -0,0 +1,8 @@
+MODULE = msado15.dll
+
+EXTRADLLFLAGS = -mno-cygwin
+
+C_SRCS = \
+ main.c \
+
+IDL_SRCS = msado15_tlb.idl
diff --git a/dlls/msado15/main.c b/dlls/msado15/main.c
new file mode 100644
index 0000000000..0c5b2615d0
--- /dev/null
+++ b/dlls/msado15/main.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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 <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "rpcproxy.h"
+
+#include "wine/debug.h"
+
+static HINSTANCE hinstance;
+
+BOOL WINAPI DllMain( HINSTANCE dll, DWORD reason, LPVOID reserved )
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ hinstance = dll;
+ DisableThreadLibraryCalls( dll );
+ break;
+ }
+ return TRUE;
+}
+
+/***********************************************************************
+ * DllRegisterServer
+ */
+HRESULT WINAPI DllRegisterServer( void )
+{
+ return __wine_register_resources( hinstance );
+}
+
+/***********************************************************************
+ * DllUnregisterServer
+ */
+HRESULT WINAPI DllUnregisterServer( void )
+{
+ return __wine_unregister_resources( hinstance );
+}
diff --git a/dlls/msado15/msado15.spec b/dlls/msado15/msado15.spec
new file mode 100644
index 0000000000..6d0e061a53
--- /dev/null
+++ b/dlls/msado15/msado15.spec
@@ -0,0 +1,4 @@
+@ stub DllCanUnloadNow
+@ stub DllGetClassObject
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
diff --git a/dlls/msado15/msado15_tlb.idl b/dlls/msado15/msado15_tlb.idl
new file mode 100644
index 0000000000..f3a77df3ac
--- /dev/null
+++ b/dlls/msado15/msado15_tlb.idl
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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 regtypelib
+
+#include "msado15_backcompat.idl"
diff --git a/include/Makefile.in b/include/Makefile.in
index 421e3d6c59..2e9a921df7 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -394,6 +394,7 @@ SOURCES = \
msacm.h \
msacmdlg.h \
msacmdrv.h \
+ msado15_backcompat.idl \
msasn1.h \
mscat.h \
mscoree.idl \
diff --git a/include/msado15_backcompat.idl b/include/msado15_backcompat.idl
new file mode 100644
index 0000000000..1ff81cf856
--- /dev/null
+++ b/include/msado15_backcompat.idl
@@ -0,0 +1,2104 @@
+/*
+ * Copyright 2019 Hans Leidekker for CodeWeavers
+ *
+ * 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
+ */
+
+import "oaidl.idl";
+
+interface _ADO;
+interface _Collection;
+interface _Command;
+interface _Connection;
+interface _DynaCollection;
+interface _Parameter;
+interface _Record;
+interface _Recordset;
+interface _Stream;
+interface ADODebugging;
+interface ADOConnectionConstruction;
+interface ADOCommandConstruction;
+interface ADORecordsetConstruction;
+interface Command15;
+interface Command25;
+interface Error;
+interface Errors;
+interface Field;
+interface Field15;
+interface Field20;
+interface Fields;
+interface Fields15;
+interface Fields20;
+interface Parameters;
+interface Properties;
+interface Property;
+interface Recordset15;
+interface Recordset20;
+interface Recordset21;
+dispinterface ConnectionEvents;
+dispinterface RecordsetEvents;
+
+typedef [uuid(0000052A-0000-0010-8000-00AA006D2EA4)] enum ErrorValueEnum
+{
+ adErrInvalidArgument = 3001,
+ adErrOpeningFile = 3002,
+ adErrReadFile = 3003,
+ adErrWriteFile = 3004,
+ adErrNoCurrentRecord = 3021,
+ adErrIllegalOperation = 3219,
+ adErrCantChangeProvider = 3220,
+ adErrInTransaction = 3246,
+ adErrFeatureNotAvailable = 3251,
+ adErrItemNotFound = 3265,
+ adErrObjectInCollection = 3367,
+ adErrObjectNotSet = 3420,
+ adErrDataConversion = 3421,
+ adErrObjectClosed = 3704,
+ adErrObjectOpen = 3705,
+ adErrProviderNotFound = 3706,
+ adErrBoundToCommand = 3707,
+ adErrInvalidParamInfo = 3708,
+ adErrInvalidConnection = 3709,
+ adErrNotReentrant = 3710,
+ adErrStillExecuting = 3711,
+ adErrOperationCancelled = 3712,
+ adErrStillConnecting = 3713,
+ adErrInvalidTransaction = 3714,
+ adErrNotExecuting = 3715,
+ adErrUnsafeOperation = 3716,
+ adWrnSecurityDialog = 3717,
+ adWrnSecurityDialogHeader = 3718,
+ adErrIntegrityViolation = 3719,
+ adErrPermissionDenied = 3720,
+ adErrDataOverflow = 3721,
+ adErrSchemaViolation = 3722,
+ adErrSignMismatch = 3723,
+ adErrCantConvertvalue = 3724,
+ adErrCantCreate = 3725,
+ adErrColumnNotOnThisRow = 3726,
+ adErrURLDoesNotExist = 3727,
+ adErrTreePermissionDenied = 3728,
+ adErrInvalidURL = 3729,
+ adErrResourceLocked = 3730,
+ adErrResourceExists = 3731,
+ adErrCannotComplete = 3732,
+ adErrVolumeNotFound = 3733,
+ adErrOutOfSpace = 3734,
+ adErrResourceOutOfScope = 3735,
+ adErrUnavailable = 3736,
+ adErrURLNamedRowDoesNotExist = 3737,
+ adErrDelResOutOfScope = 3738,
+ adErrPropInvalidColumn = 3739,
+ adErrPropInvalidOption = 3740,
+ adErrPropInvalidValue = 3741,
+ adErrPropConflicting = 3742,
+ adErrPropNotAllSettable = 3743,
+ adErrPropNotSet = 3744,
+ adErrPropNotSettable = 3745,
+ adErrPropNotSupported = 3746,
+ adErrCatalogNotSet = 3747,
+ adErrCantChangeConnection = 3748,
+ adErrFieldsUpdateFailed = 3749,
+ adErrDenyNotSupported = 3750,
+ adErrDenyTypeNotSupported = 3751,
+ adErrProviderNotSpecified = 3753,
+ adErrConnectionStringTooLong = 3754
+} ErrorValueEnum;
+
+typedef [uuid(00000528-0000-0010-8000-00aa006d2ea4)] enum PositionEnum
+{
+ adPosUnknown = -1,
+ adPosBOF = -2,
+ adPosEOF = -3
+} PositionEnum;
+
+typedef [uuid(a56187c5-d690-4037-ae32-a00edc376ac3), public] PositionEnum PositionEnum_Param;
+
+typedef [uuid(0000051f-0000-0010-8000-00aa006d2ea4)] enum DataTypeEnum
+{
+ adEmpty = 0,
+ adTinyInt = 16,
+ adSmallInt = 2,
+ adInteger = 3,
+ adBigInt = 20,
+ adUnsignedTinyInt = 17,
+ adUnsignedSmallInt = 18,
+ adUnsignedInt = 19,
+ adUnsignedBigInt = 21,
+ adSingle = 4,
+ adDouble = 5,
+ adCurrency = 6,
+ adDecimal = 14,
+ adNumeric = 131,
+ adBoolean = 11,
+ adError = 10,
+ adUserDefined = 132,
+ adVariant = 12,
+ adIDispatch = 9,
+ adIUnknown = 13,
+ adGUID = 72,
+ adDate = 7,
+ adDBDate = 133,
+ adDBTime = 134,
+ adDBTimeStamp = 135,
+ adBSTR = 8,
+ adChar = 129,
+ adVarChar = 200,
+ adLongVarChar = 201,
+ adWChar = 130,
+ adVarWChar = 202,
+ adLongVarWChar = 203,
+ adBinary = 128,
+ adVarBinary = 204,
+ adLongVarBinary = 205,
+ adChapter = 136,
+ adFileTime = 64,
+ adPropVariant = 138,
+ adVarNumeric = 139,
+ adArray = 0x2000
+} DataTypeEnum;
+
+typedef [uuid(00000548-0000-0010-8000-00aa006d2ea4)] enum PersistFormatEnum
+{
+ adPersistADTG = 0,
+ adPersistXML = 1
+} PersistFormatEnum;
+
+typedef [uuid(00000552-0000-0010-8000-00aa006d2ea4)] enum SeekEnum
+{
+ adSeekFirstEQ = 1,
+ adSeekLastEQ = 2,
+ adSeekAfterEQ = 4,
+ adSeekAfter = 8,
+ adSeekBeforeEQ = 16,
+ adSeekBefore = 32
+} SeekEnum;
+
+typedef [uuid(0000051b-0000-0010-8000-00aa006d2ea4)] enum CursorTypeEnum
+{
+ adOpenUnspecified = -1,
+ adOpenForwardOnly = 0,
+ adOpenKeyset = 1,
+ adOpenDynamic = 2,
+ adOpenStatic = 3
+} CursorTypeEnum;
+
+typedef [uuid(00000525-0000-0010-8000-00aa006d2ea4)] enum FieldAttributeEnum
+{
+ adFldUnspecified = -1,
+ adFldMayDefer = 0x00000002,
+ adFldUpdatable = 0x00000004,
+ adFldUnknownUpdatable = 0x00000008,
+ adFldFixed = 0x00000010,
+ adFldIsNullable = 0x00000020,
+ adFldMayBeNull = 0x00000040,
+ adFldLong = 0x00000080,
+ adFldRowID = 0x00000100,
+ adFldRowVersion = 0x00000200,
+ adFldCacheDeferred = 0x00001000,
+ adFldIsChapter = 0x00002000,
+ adFldNegativeScale = 0x00004000,
+ adFldKeyColumn = 0x00008000,
+ adFldIsRowURL = 0x00010000,
+ adFldIsDefaultStream = 0x00020000,
+ adFldIsCollection = 0x00040000
+} FieldAttributeEnum;
+
+typedef [uuid(00000544-0000-0010-8000-00aa006d2ea4)] enum ResyncEnum
+{
+ adResyncUnderlyingValues = 1,
+ adResyncAllValues = 2
+} ResyncEnum;
+
+typedef [uuid(0000051d-0000-0010-8000-00aa006d2ea4)] enum LockTypeEnum
+{
+ adLockUnspecified = -1,
+ adLockReadOnly = 1,
+ adLockPessimistic = 2,
+ adLockOptimistic = 3,
+ adLockBatchOptimistic = 4
+} LockTypeEnum;
+
+typedef [uuid(00000543-0000-0010-8000-00aa006d2ea4)] enum AffectEnum
+{
+ adAffectCurrent = 1,
+ adAffectGroup = 2,
+ adAffectAll = 3,
+ adAffectAllChapters = 4
+} AffectEnum;
+
+typedef [uuid(00000526-0000-0010-8000-00aa006d2ea4)] enum EditModeEnum
+{
+ adEditNone = 0,
+ adEditInProgress = 1,
+ adEditAdd = 2,
+ adEditDelete = 4
+} EditModeEnum;
+
+typedef [uuid(0000052f-0000-0010-8000-00aa006d2ea4)] enum CursorLocationEnum
+{
+ adUseNone = 1,
+ adUseServer = 2,
+ adUseClient = 3,
+ adUseClientBatch = 3
+} CursorLocationEnum;
+
+typedef [uuid(0000051c-0000-0010-8000-00aa006d2ea4)] enum CursorOptionEnum
+{
+ adHoldRecords = 256,
+ adMovePrevious = 512,
+ adBookmark = 8192,
+ adApproxPosition = 16384,
+ adUpdateBatch = 65536,
+ adResync = 131072,
+ adNotify = 262144,
+ adFind = 524288,
+ adSeek = 4194304,
+ adIndex = 8388608,
+ adAddNew = 16778240,
+ adDelete = 16779264,
+ adUpdate = 16809984
+} CursorOptionEnum;
+
+typedef [uuid(00000540-0000-0010-8000-00aa006d2ea4)] enum MarshalOptionsEnum
+{
+ adMarshalAll = 0,
+ adMarshalModifiedOnly = 1
+} MarshalOptionsEnum;
+
+typedef [uuid(00000547-0000-0010-8000-00aa006d2ea4)] enum SearchDirectionEnum
+{
+ adSearchForward = 1,
+ adSearchBackward = -1
+} SearchDirectionEnum;
+
+typedef [uuid(00000549-0000-0010-8000-00aa006d2ea4)] enum StringFormatEnum
+{
+ adClipString = 2
+} StringFormatEnum;
+
+typedef [uuid(00000545-0000-0010-8000-00aa006d2ea4)] enum CompareEnum
+{
+ adCompareLessThan = 0,
+ adCompareEqual = 1,
+ adCompareGreaterThan = 2,
+ adCompareNotEqual = 3,
+ adCompareNotComparable = 4
+} CompareEnum;
+
+typedef [uuid(00000523-0000-0010-8000-00aa006d2ea4)] enum IsolationLevelEnum
+{
+ adXactUnspecified = -1,
+ adXactChaos = 16,
+ adXactReadUncommitted = 256,
+ adXactBrowse = 256,
+ adXactCursorStability = 4096,
+ adXactReadCommitted = 4096,
+ adXactRepeatableRead = 65536,
+ adXactSerializable = 1048576,
+ adXactIsolated = 1048576
+} IsolationLevelEnum;
+
+typedef [uuid(00000521-0000-0010-8000-00aa006d2ea4)] enum ConnectModeEnum
+{
+ adModeUnknown = 0,
+ adModeRead = 1,
+ adModeWrite = 2,
+ adModeReadWrite = 3,
+ adModeShareDenyRead = 4,
+ adModeShareDenyWrite = 8,
+ adModeShareExclusive = 12,
+ adModeShareDenyNone = 16,
+ adModeRecursive = 4194304
+} ConnectModeEnum;
+
+typedef [uuid(00000533-0000-0010-8000-00aa006d2ea4)] enum SchemaEnum
+{
+ adSchemaProviderSpecific = -1,
+ adSchemaAsserts = 0,
+ adSchemaCatalogs = 1,
+ adSchemaCharacterSets = 2,
+ adSchemaCollations = 3,
+ adSchemaColumns = 4,
+ adSchemaCheckConstraints = 5,
+ adSchemaConstraintColumnUsage = 6,
+ adSchemaConstraintTableUsage = 7,
+ adSchemaKeyColumnUsage = 8,
+ adSchemaReferentialContraints = 9,
+ adSchemaReferentialConstraints = 9,
+ adSchemaTableConstraints = 10,
+ adSchemaColumnsDomainUsage = 11,
+ adSchemaIndexes = 12,
+ adSchemaColumnPrivileges = 13,
+ adSchemaTablePrivileges = 14,
+ adSchemaUsagePrivileges = 15,
+ adSchemaProcedures = 16,
+ adSchemaSchemata = 17,
+ adSchemaSQLLanguages = 18,
+ adSchemaStatistics = 19,
+ adSchemaTables = 20,
+ adSchemaTranslations = 21,
+ adSchemaProviderTypes = 22,
+ adSchemaViews = 23,
+ adSchemaViewColumnUsage = 24,
+ adSchemaViewTableUsage = 25,
+ adSchemaProcedureParameters = 26,
+ adSchemaForeignKeys = 27,
+ adSchemaPrimaryKeys = 28,
+ adSchemaProcedureColumns = 29,
+ adSchemaDBInfoKeywords = 30,
+ adSchemaDBInfoLiterals = 31,
+ adSchemaCubes = 32,
+ adSchemaDimensions = 33,
+ adSchemaHierarchies = 34,
+ adSchemaLevels = 35,
+ adSchemaMeasures = 36,
+ adSchemaProperties = 37,
+ adSchemaMembers = 38,
+ adSchemaTrustees = 39,
+ adSchemaFunctions = 40,
+ adSchemaActions = 41,
+ adSchemaCommands = 42,
+ adSchemaSets = 43
+} SchemaEnum;
+
+typedef [uuid(00000530-0000-0010-8000-00aa006d2ea4)] enum EventStatusEnum
+{
+ adStatusOK = 1,
+ adStatusErrorsOccurred = 2,
+ adStatusCantDeny = 3,
+ adStatusCancel = 4,
+ adStatusUnwantedEvent = 5
+} EventStatusEnum;
+
+typedef [uuid(0000052c-0000-0010-8000-00aa006d2ea4)] enum ParameterDirectionEnum
+{
+ adParamUnknown = 0,
+ adParamInput = 1,
+ adParamOutput = 2,
+ adParamInputOutput = 3,
+ adParamReturnValue = 4
+} ParameterDirectionEnum;
+
+typedef [uuid(0000052e-0000-0010-8000-00aa006d2ea4)] enum CommandTypeEnum
+{
+ adCmdUnspecified = -1,
+ adCmdUnknown = 8,
+ adCmdText = 1,
+ adCmdTable = 2,
+ adCmdStoredProc = 4,
+ adCmdFile = 256,
+ adCmdTableDirect = 512
+} CommandTypeEnum;
+
+typedef [uuid(00000532-0000-0010-8000-00aa006d2ea4)] enum ObjectStateEnum
+{
+ adStateClosed = 0,
+ adStateOpen = 1,
+ adStateConnecting = 2,
+ adStateExecuting = 4,
+ adStateFetching = 8
+} ObjectStateEnum;
+
+typedef [uuid(00000573-0000-0010-8000-00aa006d2ea4)] enum MoveRecordOptionsEnum
+{
+ adMoveUnspecified = -1,
+ adMoveOverWrite = 1,
+ adMoveDontUpdateLinks = 2,
+ adMoveAllowEmulation = 4
+} MoveRecordOptionsEnum;
+
+typedef [uuid(00000574-0000-0010-8000-00aa006d2ea4)] enum CopyRecordOptionsEnum
+{
+ adCopyUnspecified = -1,
+ adCopyOverWrite = 1,
+ adCopyAllowEmulation = 4,
+ adCopyNonRecursive = 2
+} CopyRecordOptionsEnum;
+
+typedef [uuid(00000570-0000-0010-8000-00aa006d2ea4)] enum RecordCreateOptionsEnum
+{
+ adCreateCollection = 0x00002000,
+ adCreateStructDoc = 0x80000000,
+ adCreateNonCollection = 0x00000000,
+ adOpenIfExists = 0x02000000,
+ adCreateOverwrite = 0x04000000,
+ adFailIfNotExists = -1
+} RecordCreateOptionsEnum;
+
+typedef [uuid(00000571-0000-0010-8000-00aa006d2ea4)] enum RecordOpenOptionsEnum
+{
+ adOpenRecordUnspecified = -1,
+ adOpenOutput = 0x00800000,
+ adOpenAsync = 0x00001000,
+ adDelayFetchStream = 0x00004000,
+ adDelayFetchFields = 0x00008000,
+ adOpenExecuteCommand = 0x00010000
+} RecordOpenOptionsEnum;
+
+typedef [uuid(0000057d-0000-0010-8000-00aa006d2ea4)] enum RecordTypeEnum
+{
+ adSimpleRecord = 0,
+ adCollectionRecord = 1,
+ adStructDoc = 2
+} RecordTypeEnum;
+
+typedef [uuid(00000576-0000-0010-8000-00aa006d2ea4)] enum StreamTypeEnum
+{
+ adTypeBinary = 1,
+ adTypeText = 2
+} StreamTypeEnum;
+
+typedef [uuid(00000577-0000-0010-8000-00aa006d2ea4)] enum LineSeparatorEnum
+{
+ adLF = 10,
+ adCR = 13,
+ adCRLF = -1
+} LineSeparatorEnum;
+
+typedef enum
+{
+ adReadAll = -1,
+ adReadLine = -2
+} StreamReadEnum;
+
+typedef [uuid(0000057c-0000-0010-8000-00aa006d2ea4)] enum SaveOptionsEnum
+{
+ adSaveCreateNotExist = 1,
+ adSaveCreateOverWrite = 2
+} SaveOptionsEnum;
+
+typedef [uuid(0000057a-0000-0010-8000-00aa006d2ea4)] enum StreamOpenOptionsEnum
+{
+ adOpenStreamUnspecified = -1,
+ adOpenStreamAsync = 1,
+ adOpenStreamFromRecord = 4
+} StreamOpenOptionsEnum;
+
+typedef [uuid(0000057b-0000-0010-8000-00aa006d2ea4)] enum StreamWriteEnum
+{
+ adWriteChar = 0,
+ adWriteLine = 1
+} StreamWriteEnum;
+
+typedef [uuid(00000531-0000-0010-8000-00aa006d2ea4)] enum EventReasonEnum
+{
+ adRsnAddNew = 1,
+ adRsnDelete = 2,
+ adRsnUpdate = 3,
+ adRsnUndoUpdate = 4,
+ adRsnUndoAddNew = 5,
+ adRsnUndoDelete = 6,
+ adRsnRequery = 7,
+ adRsnResynch = 8,
+ adRsnClose = 9,
+ adRsnMove = 10,
+ adRsnFirstChange = 11,
+ adRsnMoveFirst = 12,
+ adRsnMoveNext = 13,
+ adRsnMovePrevious = 14,
+ adRsnMoveLast = 15
+} EventReasonEnum;
+
+[
+ uuid(00000503-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Property : IDispatch
+{
+ [id(00000000), propget]
+ HRESULT __stdcall Value(
+ [out, retval] VARIANT *val);
+
+ [id(00000000), propput]
+ HRESULT __stdcall Value(
+ [in] VARIANT val);
+
+ [id(0x60020002), propget]
+ HRESULT __stdcall Name(
+ [out, retval] BSTR *str);
+
+ [id(0x60020003), propget]
+ HRESULT __stdcall Type(
+ [out, retval] DataTypeEnum *type);
+
+ [id(0x60020004), propget]
+ HRESULT __stdcall Attributes(
+ [out, retval] LONG *attributes);
+
+ [id(0x60020004), propput]
+ HRESULT __stdcall Attributes(
+ [in] LONG attributes);
+};
+
+[
+ uuid(00000512-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface _Collection : IDispatch
+{
+ [id(0x60020000), propget]
+ HRESULT __stdcall Count(
+ [out, retval] LONG *count);
+
+ [id(0xfffffffc), restricted]
+ HRESULT __stdcall _NewEnum(
+ [out, retval] IUnknown **object);
+
+ [id(0x60020002)]
+ HRESULT __stdcall Refresh();
+};
+
+[
+ uuid(00000504-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Properties : _Collection
+{
+ [id(00000000), propget]
+ HRESULT __stdcall Item(
+ [in] VARIANT index,
+ [out, retval] Property **object);
+};
+
+[
+ uuid(00000534-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface _ADO : IDispatch
+{
+ [id(0x000001f4), propget]
+ HRESULT __stdcall Properties(
+ [out, retval] Properties **object);
+};
+
+[
+ uuid(0000054c-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation,
+ hidden
+]
+interface Field20 : _ADO
+{
+ [id(0x00000455), propget]
+ HRESULT __stdcall ActualSize(
+ [out, retval] LONG *size);
+
+ [id(0x0000040c), propget]
+ HRESULT __stdcall Attributes(
+ [out, retval] LONG *attrs);
+
+ [id(0x0000044f), propget]
+ HRESULT __stdcall DefinedSize(
+ [out, retval] LONG *size);
+
+ [id(0x0000044c), propget]
+ HRESULT __stdcall Name(
+ [out, retval] BSTR *str);
+
+ [id(0x0000044e), propget]
+ HRESULT __stdcall Type(
+ [out, retval] DataTypeEnum *type);
+
+ [id(00000000), propget]
+ HRESULT __stdcall Value(
+ [out, retval] VARIANT *val);
+
+ [id(00000000), propput]
+ HRESULT __stdcall Value(
+ [in] VARIANT val);
+
+ [id(0x60030007), propget]
+ HRESULT __stdcall Precision(
+ [out, retval] unsigned char *precision);
+
+ [id(0x60030008), propget]
+ HRESULT __stdcall NumericScale(
+ [out, retval] unsigned char *scale);
+
+ [id(0x00000453)]
+ HRESULT __stdcall AppendChunk(
+ [in] VARIANT data);
+
+ [id(0x00000454)]
+ HRESULT __stdcall GetChunk(
+ [in] LONG length,
+ [out, retval] VARIANT *var);
+
+ [id(0x00000450), propget]
+ HRESULT __stdcall OriginalValue(
+ [out, retval] VARIANT *val);
+
+ [id(0x00000451), propget]
+ HRESULT __stdcall UnderlyingValue(
+ [out, retval] VARIANT *val);
+
+ [id(0x6003000d), propget]
+ HRESULT __stdcall DataFormat(
+ [out, retval] IUnknown **format);
+
+ [id(0x6003000d), propputref]
+ HRESULT __stdcall DataFormat(
+ [in] IUnknown *format);
+
+ [id(0x60030007), propput]
+ HRESULT __stdcall Precision(
+ [in] unsigned char precision);
+
+ [id(0x60030008), propput]
+ HRESULT __stdcall NumericScale(
+ [in] unsigned char scale);
+
+ [id(0x0000044e), propput]
+ HRESULT __stdcall Type(
+ [in] DataTypeEnum type);
+
+ [id(0x0000044f), propput]
+ HRESULT __stdcall DefinedSize(
+ [in] LONG size);
+
+ [id(0x0000040c), propput]
+ HRESULT __stdcall Attributes(
+ [in] LONG attrs);
+};
+
+[
+ uuid(00000569-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Field : Field20
+{
+ [id(0x0000045c), propget]
+ HRESULT __stdcall Status(
+ [out, retval] LONG *status);
+};
+
+[
+ uuid(00000506-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Fields15 : _Collection
+{
+ [id(00000000), propget]
+ HRESULT __stdcall Item(
+ [in] VARIANT index,
+ [out, retval] Field **object);
+};
+
+[
+ uuid(0000054d-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Fields20 : Fields15
+{
+ [id(0x60030001)]
+ HRESULT __stdcall _Append(
+ [in] BSTR name,
+ [in] DataTypeEnum type,
+ [in, defaultvalue(0)] LONG size,
+ [in, defaultvalue(adFldUnspecified)] FieldAttributeEnum attr);
+
+ [id(0x60030002)]
+ HRESULT __stdcall Delete(
+ [in] VARIANT index);
+};
+
+[
+ uuid(00000564-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Fields : Fields20
+{
+ [id(0x60040001)]
+ HRESULT __stdcall Append(
+ [in] BSTR name,
+ [in] DataTypeEnum type,
+ [in, defaultvalue(0)] LONG size,
+ [in, defaultvalue(adFldUnspecified)] FieldAttributeEnum attr,
+ [in, optional] VARIANT value);
+
+ [id(0x60040002)]
+ HRESULT __stdcall Update();
+
+ [id(0x60040003)]
+ HRESULT __stdcall Resync(
+ [in, defaultvalue(adResyncAllValues)] ResyncEnum resync_values);
+
+ [id(0x60040004)]
+ HRESULT __stdcall CancelUpdate();
+};
+
+[
+ uuid(0000050e-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Recordset15 : _ADO
+{
+ [id(0x000003e8), propget]
+ HRESULT __stdcall AbsolutePosition(
+ [out, retval] PositionEnum_Param *position);
+
+ [id(0x000003e8), propput]
+ HRESULT __stdcall AbsolutePosition(
+ [in] PositionEnum_Param position);
+
+ [id(0x000003e9), propputref]
+ HRESULT __stdcall ActiveConnection(
+ [in] IDispatch *connection);
+
+ [id(0x000003e9), propput]
+ HRESULT __stdcall ActiveConnection(
+ [in] VARIANT connection);
+
+ [id(0x000003e9), propget]
+ HRESULT __stdcall ActiveConnection(
+ [out, retval] VARIANT *connection);
+
+ [id(0x000003ea), propget]
+ HRESULT __stdcall BOF(
+ [out, retval] VARIANT_BOOL *bof);
+
+ [id(0x000003eb), propget]
+ HRESULT __stdcall Bookmark(
+ [out, retval] VARIANT *bookmark);
+
+ [id(0x000003eb), propput]
+ HRESULT __stdcall Bookmark(
+ [in] VARIANT bookmark);
+
+ [id(0x000003ec), propget]
+ HRESULT __stdcall CacheSize(
+ [out, retval] LONG *size);
+
+ [id(0x000003ec), propput]
+ HRESULT __stdcall CacheSize(
+ [in] LONG size);
+
+ [id(0x000003ed), propget]
+ HRESULT __stdcall CursorType(
+ [out, retval] CursorTypeEnum *cursor_type);
+
+ [id(0x000003ed), propput]
+ HRESULT __stdcall CursorType(
+ [in] CursorTypeEnum cursor_type);
+
+ [id(0x000003ee), propget]
+ HRESULT __stdcall EOF(
+ [out, retval] VARIANT_BOOL *eof);
+
+ [id(00000000), propget]
+ HRESULT __stdcall Fields(
+ [out, retval] Fields **object);
+
+ [id(0x000003f0), propget]
+ HRESULT __stdcall LockType(
+ [out, retval] LockTypeEnum *lock_type);
+
+ [id(0x000003f0), propput]
+ HRESULT __stdcall LockType(
+ [in] LockTypeEnum lock_type);
+
+ [id(0x000003f1), propget]
+ HRESULT __stdcall MaxRecords(
+ [out, retval] LONG *max_records);
+
+ [id(0x000003f1), propput]
+ HRESULT __stdcall MaxRecords(
+ [in] LONG max_records);
+
+ [id(0x000003f2), propget]
+ HRESULT __stdcall RecordCount(
+ [out, retval] LONG *count);
+
+ [id(0x000003f3), propputref]
+ HRESULT __stdcall Source(
+ [in] IDispatch *source);
+
+ [id(0x000003f3), propput]
+ HRESULT __stdcall Source(
+ [in] BSTR source);
+
+ [id(0x000003f3), propget]
+ HRESULT __stdcall Source(
+ [out, retval] VARIANT *source);
+
+ [id(0x000003f4)]
+ HRESULT __stdcall AddNew(
+ [in, optional] VARIANT field_list,
+ [in, optional] VARIANT values);
+
+ [id(0x000003f5)]
+ HRESULT __stdcall CancelUpdate();
+
+ [id(0x000003f6)]
+ HRESULT __stdcall Close();
+
+ [id(0x000003f7)]
+ HRESULT __stdcall Delete(
+ [in, defaultvalue(adAffectCurrent)] AffectEnum affect_records);
+
+ [id(0x000003f8)]
+ HRESULT __stdcall GetRows(
+ [in, defaultvalue(-1)] LONG rows,
+ [in, optional] VARIANT start,
+ [in, optional] VARIANT fields,
+ [out, retval] VARIANT *var);
+
+ [id(0x000003f9)]
+ HRESULT __stdcall Move(
+ [in] LONG num_records,
+ [in, optional] VARIANT start);
+
+ [id(0x000003fa)]
+ HRESULT __stdcall MoveNext();
+
+ [id(0x000003fb)]
+ HRESULT __stdcall MovePrevious();
+
+ [id(0x000003fc)]
+ HRESULT __stdcall MoveFirst();
+
+ [id(0x000003fd)]
+ HRESULT __stdcall MoveLast();
+
+ [id(0x000003fe)]
+ HRESULT __stdcall Open(
+ [in, optional] VARIANT source,
+ [in, optional] VARIANT active_connection,
+ [in, defaultvalue(adOpenUnspecified)] CursorTypeEnum cursor_type,
+ [in, defaultvalue(adLockUnspecified)] LockTypeEnum lock_type,
+ [in, defaultvalue(-1)] LONG options);
+
+ [id(0x000003ff)]
+ HRESULT __stdcall Requery(
+ [in, defaultvalue(-1)] LONG options);
+
+ [id(0x60030022), hidden]
+ HRESULT __stdcall _xResync(
+ [in, defaultvalue(adAffectAll)] AffectEnum affect_records);
+
+ [id(0x00000401)]
+ HRESULT __stdcall Update(
+ [in, optional] VARIANT fields,
+ [in, optional] VARIANT values);
+
+ [id(0x00000417), propget]
+ HRESULT __stdcall AbsolutePage(
+ [out, retval] PositionEnum_Param *position);
+
+ [id(0x00000417), propput]
+ HRESULT __stdcall AbsolutePage(
+ [in] PositionEnum_Param position);
+
+ [id(0x00000402), propget]
+ HRESULT __stdcall EditMode(
+ [out, retval] EditModeEnum *mode);
+
+ [id(0x00000406), propget]
+ HRESULT __stdcall Filter(
+ [out, retval] VARIANT *criteria);
+
+ [id(0x00000406), propput]
+ HRESULT __stdcall Filter(
+ [in] VARIANT criteria);
+
+ [id(0x0000041a), propget]
+ HRESULT __stdcall PageCount(
+ [out, retval] LONG *count);
+
+ [id(0x00000418), propget]
+ HRESULT __stdcall PageSize(
+ [out, retval] LONG *size);
+
+ [id(0x00000418), propput]
+ HRESULT __stdcall PageSize(
+ [in] LONG size);
+
+ [id(0x00000407), propget]
+ HRESULT __stdcall Sort(
+ [out, retval] BSTR *criteria);
+
+ [id(0x00000407), propput]
+ HRESULT __stdcall Sort(
+ [in] BSTR criteria);
+
+ [id(0x00000405), propget]
+ HRESULT __stdcall Status(
+ [out, retval] LONG *status);
+
+ [id(0x0000041e), propget]
+ HRESULT __stdcall State(
+ [out, retval] LONG *state);
+
+ [id(0x60030030), hidden]
+ HRESULT __stdcall _xClone(
+ [out, retval] _Recordset **object);
+
+ [id(0x0000040b)]
+ HRESULT __stdcall UpdateBatch(
+ [in, defaultvalue(adAffectAll)] AffectEnum affect_records);
+
+ [id(0x00000419)]
+ HRESULT __stdcall CancelBatch(
+ [in, defaultvalue(adAffectAll)] AffectEnum affect_records);
+
+ [id(0x0000041b), propget]
+ HRESULT __stdcall CursorLocation(
+ [out, retval] CursorLocationEnum *cursor_loc);
+
+ [id(0x0000041b), propput]
+ HRESULT __stdcall CursorLocation(
+ [in] CursorLocationEnum cursor_loc);
+
+ [id(0x0000041c)]
+ HRESULT __stdcall NextRecordset(
+ [out, optional] VARIANT *records_affected,
+ [out, retval] _Recordset **record_set);
+
+ [id(0x0000040c)]
+ HRESULT __stdcall Supports(
+ [in] CursorOptionEnum cursor_options,
+ [out, retval] VARIANT_BOOL *ret);
+
+ [id(0xfffffff8), propget, hidden]
+ HRESULT __stdcall Collect(
+ [in] VARIANT index,
+ [out, retval] VARIANT *var);
+
+ [id(0xfffffff8), propput, hidden]
+ HRESULT __stdcall Collect(
+ [in] VARIANT index,
+ [in] VARIANT var);
+
+ [id(0x0000041d), propget]
+ HRESULT __stdcall MarshalOptions(
+ [out, retval] MarshalOptionsEnum *options);
+
+ [id(0x0000041d), propput]
+ HRESULT __stdcall MarshalOptions(
+ [in] MarshalOptionsEnum options);
+
+ [id(0x00000422)]
+ HRESULT __stdcall Find(
+ [in] BSTR criteria,
+ [in, defaultvalue(0)] LONG skip_records,
+ [in, defaultvalue(adSearchForward)] SearchDirectionEnum search_direction,
+ [in, optional] VARIANT start);
+};
+
+[
+ uuid(0000054f-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Recordset20 : Recordset15
+{
+ [id(0x0000041f)]
+ HRESULT __stdcall Cancel();
+
+ [id(0x00000420), propget]
+ HRESULT __stdcall DataSource(
+ [out, retval] IUnknown **data_source);
+
+ [id(0x00000420), propputref]
+ HRESULT __stdcall DataSource(
+ [in] IUnknown *data_source);
+
+ [hidden]
+ HRESULT __stdcall _xSave(
+ [in, optional] BSTR filename,
+ [in, defaultvalue(adPersistADTG)] PersistFormatEnum persist_format);
+
+ [id(0x00000425), propget]
+ HRESULT __stdcall ActiveCommand(
+ [out, retval] IDispatch **cmd);
+
+ [id(0x00000427), propput]
+ HRESULT __stdcall StayInSync(
+ [in] VARIANT_BOOL stay_in_sync);
+
+ [id(0x00000427), propget]
+ HRESULT __stdcall StayInSync(
+ [out, retval] VARIANT_BOOL *stay_in_sync);
+
+ [id(0x00000426)]
+ HRESULT __stdcall GetString(
+ [in, defaultvalue(adClipString)] StringFormatEnum string_format,
+ [in, defaultvalue(-1)] LONG num_rows,
+ [in, optional] BSTR column_delimeter,
+ [in, optional] BSTR row_delimeter,
+ [in, optional] BSTR null_expr,
+ [out, retval] BSTR *ret_string);
+
+ [id(0x00000428), propget]
+ HRESULT __stdcall DataMember(
+ [out, retval] BSTR *data_member);
+
+ [id(0x00000428), propput]
+ HRESULT __stdcall DataMember(
+ [in] BSTR data_member);
+
+ [id(0x00000429)]
+ HRESULT __stdcall CompareBookmarks(
+ [in] VARIANT bookmark1,
+ [in] VARIANT bookmark2,
+ [out, retval] CompareEnum *compare);
+
+ [id(0x0000040a)]
+ HRESULT __stdcall Clone(
+ [in, defaultvalue(adLockUnspecified)] LockTypeEnum lock_type,
+ [out, retval] _Recordset **object);
+
+ [id(0x00000400)]
+ HRESULT __stdcall Resync(
+ [in, defaultvalue(adAffectAll)] AffectEnum affect_records,
+ [in, defaultvalue(adResyncAllValues)] ResyncEnum resync_values);
+};
+
+[
+ uuid(00000555-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Recordset21 : Recordset20
+{
+ [id(0x0000042a)]
+ HRESULT __stdcall Seek(
+ [in] VARIANT key_values,
+ [in, defaultvalue(adSeekFirstEQ)] SeekEnum seek_option);
+
+ [id(0x0000042b), propput]
+ HRESULT __stdcall Index(
+ [in] BSTR index);
+
+ [id(0x0000042b), propget]
+ HRESULT __stdcall Index(
+ [out, retval] BSTR *index);
+};
+
+[
+ uuid(00000556-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface _Recordset : Recordset21
+{
+ [id(0x00000421)]
+ HRESULT Save(
+ [in, optional] VARIANT destination,
+ [in, defaultvalue(adPersistADTG)] PersistFormatEnum persist_format);
+};
+
+[
+ uuid(00000500-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Error : IDispatch
+{
+ [id(0x60020000), propget]
+ HRESULT __stdcall Number(
+ [out, retval] LONG *number);
+
+ [id(0x60020001), propget]
+ HRESULT __stdcall Source(
+ [out, retval] BSTR *str);
+
+ [id(00000000), propget]
+ HRESULT __stdcall Description(
+ [out, retval] BSTR *str);
+
+ [id(0x60020003), propget]
+ HRESULT __stdcall HelpFile(
+ [out, retval] BSTR *str);
+
+ [id(0x60020004), propget]
+ HRESULT __stdcall HelpContext(
+ [out, retval] LONG *ctx);
+
+ [id(0x60020005), propget]
+ HRESULT __stdcall SQLState(
+ [out, retval] BSTR *str);
+
+ [id(0x60020006), propget]
+ HRESULT __stdcall NativeError(
+ [out, retval] LONG *error);
+};
+
+[
+ uuid(00000501-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Errors : _Collection
+{
+ [id(00000000), propget]
+ HRESULT __stdcall Item(
+ [in] VARIANT index,
+ [out, retval] Error **object);
+
+ [id(0x60030001)]
+ HRESULT __stdcall Clear();
+};
+
+[
+ uuid(00000515-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ oleautomation
+]
+interface Connection15 : _ADO
+{
+ [id(00000000), propget]
+ HRESULT __stdcall ConnectionString(
+ [out, retval] BSTR *str);
+
+ [id(00000000), propput]
+ HRESULT __stdcall ConnectionString(
+ [in] BSTR str);
+
+ [id(0x00000002), propget]
+ HRESULT __stdcall CommandTimeout(
+ [out, retval] LONG *timeout);
+
+ [id(0x00000002), propput]
+ HRESULT __stdcall CommandTimeout(
+ [in] LONG timeout);
+
+ [id(0x00000003), propget]
+ HRESULT __stdcall ConnectionTimeout(
+ [out, retval] LONG *timeout);
+
+ [id(0x00000003), propput]
+ HRESULT __stdcall ConnectionTimeout(
+ [in] LONG timeout);
+
+ [id(0x00000004), propget]
+ HRESULT __stdcall Version(
+ [out, retval] BSTR *str);
+
+ [id(0x00000005)]
+ HRESULT __stdcall Close();
+
+ [id(0x00000006)]
+ HRESULT __stdcall Execute(
+ [in] BSTR command,
+ [out, optional] VARIANT *records_affected,
+ [in, defaultvalue(-1)] LONG options,
+ [out, retval] _Recordset **record_set);
+
+ [id(0x00000007)]
+ HRESULT __stdcall BeginTrans(
+ [out, retval] LONG *transaction_level);
+
+ [id(0x00000008)]
+ HRESULT __stdcall CommitTrans();
+
+ [id(0x00000009)]
+ HRESULT __stdcall RollbackTrans();
+
+ [id(0x0000000a)]
+ HRESULT __stdcall Open(
+ [in, defaultvalue("")] BSTR connection_str,
+ [in, defaultvalue("")] BSTR user_id,
+ [in, defaultvalue("")] BSTR password,
+ [in, defaultvalue(-1)] LONG options);
+
+ [id(0x0000000b), propget]
+ HRESULT __stdcall Errors(
+ [out, retval] Errors **object);
+
+ [id(0x0000000c), propget]
+ HRESULT __stdcall DefaultDatabase(
+ [out, retval] BSTR *str);
+
+ [id(0x0000000c), propput]
+ HRESULT __stdcall DefaultDatabase(
+ [in] BSTR str);
+
+ [id(0x0000000d), propget]
+ HRESULT __stdcall IsolationLevel(
+ [out, retval] IsolationLevelEnum *level);
+
+ [id(0x0000000d), propput]
+ HRESULT __stdcall IsolationLevel(
+ [in] IsolationLevelEnum level);
+
+ [id(0x0000000e), propget]
+ HRESULT __stdcall Attributes(
+ [out, retval] LONG *attr);
+
+ [id(0x0000000e), propput]
+ HRESULT __stdcall Attributes(
+ [in] LONG attr);
+
+ [id(0x0000000f), propget]
+ HRESULT __stdcall CursorLocation(
+ [out, retval] CursorLocationEnum *cursor_loc);
+
+ [id(0x0000000f), propput]
+ HRESULT __stdcall CursorLocation(
+ [in] CursorLocationEnum cursor_loc);
+
+ [id(0x00000010), propget]
+ HRESULT __stdcall Mode(
+ [out, retval] ConnectModeEnum *mode);
+
+ [id(0x00000010), propput]
+ HRESULT __stdcall Mode(
+ [in] ConnectModeEnum mode);
+
+ [id(0x00000011), propget]
+ HRESULT __stdcall Provider(
+ [out, retval] BSTR *str);
+
+ [id(0x00000011), propput]
+ HRESULT __stdcall Provider(
+ [in] BSTR str);
+
+ [id(0x00000012), propget]
+ HRESULT __stdcall State(
+ [out, retval] LONG *state);
+
+ [id(0x00000013)]
+ HRESULT __stdcall OpenSchema(
+ [in] SchemaEnum schema,
+ [in, optional] VARIANT restrictions,
+ [in, optional] VARIANT schema_id,
+ [out, retval] _Recordset **record_set);
+};
+
+[
+ uuid(00000550-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ oleautomation
+]
+interface _Connection : Connection15
+{
+ [id(0x00000015)]
+ HRESULT __stdcall Cancel();
+};
+
+[
+ uuid(0000050c-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface _Parameter : _ADO
+{
+ [id(0x60030000), propget]
+ HRESULT __stdcall Name(
+ [out, retval] BSTR *str);
+
+ [id(0x60030000), propput]
+ HRESULT __stdcall Name(
+ [in] BSTR str);
+
+ [id(00000000), propget]
+ HRESULT __stdcall Value(
+ [out, retval] VARIANT *val);
+
+ [id(00000000), propput]
+ HRESULT __stdcall Value(
+ [in] VARIANT val);
+
+ [id(0x60030004), propget]
+ HRESULT __stdcall Type(
+ [out, retval] DataTypeEnum *data_type);
+
+ [id(0x60030004), propput]
+ HRESULT __stdcall Type(
+ [in] DataTypeEnum data_type);
+
+ [id(0x60030006), propput]
+ HRESULT __stdcall Direction(
+ [in] ParameterDirectionEnum direction);
+
+ [id(0x60030006), propget]
+ HRESULT __stdcall Direction(
+ [out, retval] ParameterDirectionEnum *direction);
+
+ [id(0x60030008), propput]
+ HRESULT __stdcall Precision(
+ [in] unsigned char precision);
+
+ [id(0x60030008), propget]
+ HRESULT __stdcall Precision(
+ [out, retval] unsigned char *precision);
+
+ [id(0x6003000a), propput]
+ HRESULT __stdcall NumericScale(
+ [in] unsigned char scale);
+
+ [id(0x6003000a), propget]
+ HRESULT __stdcall NumericScale(
+ [out, retval] unsigned char *scale);
+
+ [id(0x6003000c), propput]
+ HRESULT __stdcall Size(
+ [in] LONG size);
+
+ [id(0x6003000c), propget]
+ HRESULT __stdcall Size(
+ [out, retval] LONG *size);
+
+ [id(0x6003000e)]
+ HRESULT __stdcall AppendChunk(
+ [in] VARIANT val);
+
+ [id(0x6003000f), propget]
+ HRESULT __stdcall Attributes(
+ [out, retval] LONG *attrs);
+
+ [id(0x6003000f), propput]
+ HRESULT __stdcall Attributes(
+ [in] LONG attrs);
+};
+
+[
+ uuid(00000513-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface _DynaCollection : _Collection
+{
+ [id(0x60030000)]
+ HRESULT __stdcall Append(
+ [in] IDispatch *object);
+
+ [id(0x60030001)]
+ HRESULT __stdcall Delete(
+ [in] VARIANT index);
+};
+
+[
+ uuid(0000050d-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Parameters : _DynaCollection
+{
+ [id(00000000), propget]
+ HRESULT __stdcall Item(
+ [in] VARIANT index,
+ [out, retval] _Parameter **object);
+};
+
+[
+ uuid(00000508-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Command15 : _ADO
+{
+ [id(0x60030000), propget]
+ HRESULT __stdcall ActiveConnection(
+ [out, retval] _Connection **object);
+
+ [id(0x60030000), propputref]
+ HRESULT __stdcall ActiveConnection(
+ [in] _Connection *object);
+
+ [id(0x60030000), propput]
+ HRESULT __stdcall ActiveConnection(
+ [in] VARIANT object);
+
+ [id(0x60030003), propget]
+ HRESULT __stdcall CommandText(
+ [out, retval] BSTR *str);
+
+ [id(0x60030003), propput]
+ HRESULT __stdcall CommandText(
+ [in] BSTR str);
+
+ [id(0x60030005), propget]
+ HRESULT __stdcall CommandTimeout(
+ [out, retval] LONG *timeout);
+
+ [id(0x60030005), propput]
+ HRESULT __stdcall CommandTimeout(
+ [in] LONG timeout);
+
+ [id(0x60030007), propget]
+ HRESULT __stdcall Prepared(
+ [out, retval] VARIANT_BOOL *prepared);
+
+ [id(0x60030007), propput]
+ HRESULT __stdcall Prepared(
+ [in] VARIANT_BOOL prepared);
+
+ [id(0x60030009)]
+ HRESULT __stdcall Execute(
+ [out, optional] VARIANT *records_affected,
+ [in, optional] VARIANT *parameters,
+ [in, defaultvalue(-1)] LONG options,
+ [out, retval] _Recordset **record_set);
+
+ [id(0x6003000a)]
+ HRESULT __stdcall CreateParameter(
+ [in, defaultvalue("")] BSTR name,
+ [in, defaultvalue(adEmpty)] DataTypeEnum type,
+ [in, defaultvalue(adParamInput)] ParameterDirectionEnum direction,
+ [in, defaultvalue(0)] LONG size,
+ [in, optional] VARIANT value,
+ [out, retval] _Parameter **parameter);
+
+ [id(00000000), propget]
+ HRESULT __stdcall Parameters(
+ [out, retval] Parameters **object);
+
+ [id(0x6003000c), propput]
+ HRESULT __stdcall CommandType(
+ [in] CommandTypeEnum cmd_type);
+
+ [id(0x6003000c), propget]
+ HRESULT __stdcall CommandType(
+ [out, retval] CommandTypeEnum *cmd_type);
+
+ [id(0x6003000e), propget]
+ HRESULT __stdcall Name(
+ [out, retval] BSTR *name);
+
+ [id(0x6003000e), propput]
+ HRESULT __stdcall Name(
+ [in] BSTR name);
+};
+
+[
+ uuid(0000054e-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface Command25 : Command15
+{
+ [id(0x60030010), propget]
+ HRESULT __stdcall State(
+ [out, retval] LONG *state);
+
+ [id(0x60030011)]
+ HRESULT __stdcall Cancel();
+};
+
+[
+ uuid(b08400bd-f9d1-4d02-b856-71d5dba123e9),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface _Command : Command25
+{
+ [id(0x60030012), propputref]
+ HRESULT __stdcall CommandStream(
+ [in] IUnknown *stream);
+
+ [id(0x60030012), propget]
+ HRESULT __stdcall CommandStream(
+ [out, retval] VARIANT *stream);
+
+ [id(0x60030013), propput]
+ HRESULT __stdcall Dialect(
+ [in] BSTR dialect);
+
+ [id(0x60030013), propget]
+ HRESULT __stdcall Dialect(
+ [out, retval] BSTR *dialect);
+
+ [id(0x60030014), propput]
+ HRESULT __stdcall NamedParameters(
+ [in] VARIANT_BOOL named_parameters);
+
+ [id(0x60030014), propget]
+ HRESULT __stdcall NamedParameters(
+ [out, retval] VARIANT_BOOL *named_parameters);
+};
+
+[
+ uuid(00000400-0000-0010-8000-00aa006d2ea4)
+]
+dispinterface ConnectionEvents
+{
+ properties:
+ methods:
+ [id(00000000)]
+ HRESULT InfoMessage(
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Connection *Connection);
+
+ [id(0x00000001)]
+ HRESULT BeginTransComplete(
+ [in] LONG TransactionLevel,
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Connection *connection);
+
+ [id(0x00000003)]
+ HRESULT CommitTransComplete(
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Connection *connection);
+
+ [id(0x00000002)]
+ HRESULT RollbackTransComplete(
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Connection *connection);
+
+ [id(0x00000004)]
+ HRESULT WillExecute(
+ [in, out] BSTR *source,
+ [in, out] CursorTypeEnum *cursor_type,
+ [in, out] LockTypeEnum *lock_type,
+ [in, out] LONG *options,
+ [in, out] EventStatusEnum *status,
+ [in] _Command *command,
+ [in] _Recordset *record_set,
+ [in] _Connection *connection);
+
+ [id(0x00000005)]
+ HRESULT ExecuteComplete(
+ [in] LONG records_affected,
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Command *command,
+ [in] _Recordset *record_set,
+ [in] _Connection *connection);
+
+ [id(0x00000006)]
+ HRESULT WillConnect(
+ [in, out] BSTR *string,
+ [in, out] BSTR *userid,
+ [in, out] BSTR *password,
+ [in, out] LONG *options,
+ [in, out] EventStatusEnum *status,
+ [in] _Connection *connection);
+
+ [id(0x00000007)]
+ HRESULT ConnectComplete(
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Connection *connection);
+
+ [id(0x00000008)]
+ HRESULT Disconnect(
+ [in, out] EventStatusEnum *status,
+ [in] _Connection *connection);
+};
+
+[
+ uuid(00000562-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface _Record : _ADO
+{
+ [id(1), propget]
+ HRESULT __stdcall ActiveConnection(
+ [out, retval] VARIANT *connection);
+
+ [id(1), propput]
+ HRESULT __stdcall ActiveConnection(
+ [in] BSTR connection);
+
+ [id(1), propputref]
+ HRESULT ActiveConnection(
+ [in] _Connection *connection);
+
+ [id(2), propget]
+ HRESULT __stdcall State(
+ [out, retval] ObjectStateEnum *state);
+
+ [id(3), propget]
+ HRESULT __stdcall Source(
+ [out, retval] VARIANT *source);
+
+ [id(3), propput]
+ HRESULT __stdcall Source(
+ [in] BSTR source);
+
+ [id(3), propputref]
+ HRESULT __stdcall Source(
+ [in] IDispatch *source);
+
+ [id(4), propget]
+ HRESULT __stdcall Mode(
+ [out, retval] ConnectModeEnum *mode);
+
+ [id(4), propput]
+ HRESULT __stdcall Mode(
+ [in] ConnectModeEnum mode);
+
+ [id(5), propget]
+ HRESULT __stdcall ParentURL(
+ [out, retval] BSTR *parent_URL);
+
+ [id(6)]
+ HRESULT __stdcall MoveRecord(
+ [in, defaultvalue("")] BSTR source,
+ [in, defaultvalue("")] BSTR Destination,
+ [in, optional] BSTR UserName,
+ [in, optional] BSTR Password,
+ [in, defaultvalue(adMoveUnspecified)] MoveRecordOptionsEnum Options,
+ [in, optional] VARIANT_BOOL Async,
+ [out, retval] BSTR *pbstrNewURL);
+
+ [id(7)]
+ HRESULT __stdcall CopyRecord(
+ [in, defaultvalue("")] BSTR source,
+ [in, defaultvalue("")] BSTR destination,
+ [in, optional] BSTR username,
+ [in, optional] BSTR password,
+ [in, defaultvalue(adCopyUnspecified)] CopyRecordOptionsEnum options,
+ [in, optional] VARIANT_BOOL async,
+ [out, retval] BSTR *new_URL);
+
+ [id(8)]
+ HRESULT __stdcall DeleteRecord(
+ [in] BSTR source,
+ [in, optional] VARIANT_BOOL async);
+
+ [id(9)]
+ HRESULT __stdcall Open(
+ [in, optional] VARIANT source,
+ [in, optional] VARIANT active_connection,
+ [in, optional] ConnectModeEnum mode,
+ [in, defaultvalue(adFailIfNotExists)] RecordCreateOptionsEnum create_options,
+ [in, defaultvalue(adOpenRecordUnspecified)] RecordOpenOptionsEnum options,
+ [in, optional] BSTR username,
+ [in, optional] BSTR password);
+
+ [id(10)]
+ HRESULT __stdcall Close();
+
+ [id(0), propget]
+ HRESULT __stdcall Fields(
+ [out, retval] Fields **fields);
+
+ [id(11), propget]
+ HRESULT __stdcall RecordType(
+ [out, retval] RecordTypeEnum *type);
+
+ [id(12)]
+ HRESULT __stdcall GetChildren(
+ [out, retval] _Recordset **record_set);
+
+ [id(13)]
+ HRESULT __stdcall Cancel();
+};
+
+[
+ uuid(00000565-0000-0010-8000-00aa006d2ea4),
+ odl,
+ dual,
+ nonextensible,
+ oleautomation
+]
+interface _Stream : IDispatch
+{
+ [id(1), propget]
+ HRESULT __stdcall Size(
+ [out, retval] LONG *size);
+
+ [id(2), propget]
+ HRESULT __stdcall EOS(
+ [out, retval] VARIANT_BOOL *eos);
+
+ [id(3), propget]
+ HRESULT __stdcall Position(
+ [out, retval] LONG *position);
+
+ [id(3), propput]
+ HRESULT __stdcall Position(
+ [in] LONG position);
+
+ [id(4), propget]
+ HRESULT __stdcall Type(
+ [out, retval] StreamTypeEnum *type);
+
+ [id(4), propput]
+ HRESULT __stdcall Type(
+ [in] StreamTypeEnum type);
+
+ [id(5), propget]
+ HRESULT __stdcall LineSeparator(
+ [out, retval] LineSeparatorEnum *separator);
+
+ [id(5), propput]
+ HRESULT __stdcall LineSeparator(
+ [in] LineSeparatorEnum separator);
+
+ [id(6), propget]
+ HRESULT __stdcall State(
+ [out, retval] ObjectStateEnum *state);
+
+ [id(7), propget]
+ HRESULT __stdcall Mode(
+ [out, retval] ConnectModeEnum *mode);
+
+ [id(7), propput]
+ HRESULT __stdcall Mode(
+ [in] ConnectModeEnum mode);
+
+ [id(8), propget]
+ HRESULT Charset(
+ [out, retval] BSTR *charset);
+
+ [id(8), propput]
+ HRESULT Charset(
+ [in] BSTR charset);
+
+ [id(9)]
+ HRESULT __stdcall Read(
+ [in, defaultvalue(adReadAll)] LONG num_bytes,
+ [out, retval] VARIANT *val);
+
+ [id(10)]
+ HRESULT __stdcall Open(
+ [in, optional] VARIANT source,
+ [in, defaultvalue(adModeUnknown)] ConnectModeEnum mode,
+ [in, defaultvalue(adOpenStreamUnspecified)] StreamOpenOptionsEnum options,
+ [in, optional] BSTR username,
+ [in, optional] BSTR password);
+
+ [id(11)]
+ HRESULT __stdcall Close(void);
+
+ [id(12)]
+ HRESULT __stdcall SkipLine(void);
+
+ [id(13)]
+ HRESULT __stdcall Write(
+ [in] VARIANT buffer);
+
+ [id(14)]
+ HRESULT __stdcall SetEOS(void);
+
+ [id(15)]
+ HRESULT __stdcall CopyTo(
+ [in] _Stream *dest,
+ [in, defaultvalue(-1)] LONG size);
+
+ [id(16)]
+ HRESULT __stdcall Flush(void);
+
+ [id(17)]
+ HRESULT __stdcall SaveToFile(
+ [in] BSTR FileName,
+ [in, defaultvalue(adSaveCreateNotExist)] SaveOptionsEnum options);
+
+ [id(18)]
+ HRESULT __stdcall LoadFromFile(
+ [in] BSTR filename);
+
+ [id(19)]
+ HRESULT __stdcall ReadText(
+ [in, defaultvalue(adReadAll)] LONG size,
+ [out, retval] BSTR *str);
+
+ [id(20)]
+ HRESULT __stdcall WriteText(
+ [in] BSTR data,
+ [in, defaultvalue(adWriteChar)] StreamWriteEnum options);
+
+ [id(21)]
+ HRESULT __stdcall Cancel(void);
+};
+
+[
+ uuid(00000266-0000-0010-8000-00aa006d2ea4)
+]
+dispinterface RecordsetEvents
+{
+ properties:
+ methods:
+ [id(0x00000009)]
+ HRESULT WillChangeField(
+ [in] LONG count,
+ [in] VARIANT fields,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x0000000a)]
+ HRESULT FieldChangeComplete(
+ [in] LONG count,
+ [in] VARIANT fields,
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x0000000b)]
+ HRESULT WillChangeRecord(
+ [in] EventReasonEnum reason,
+ [in] LONG count,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x0000000c)]
+ HRESULT RecordChangeComplete(
+ [in] EventReasonEnum reason,
+ [in] LONG count,
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x0000000d)]
+ HRESULT WillChangeRecordset(
+ [in] EventReasonEnum reason,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x0000000e)]
+ HRESULT RecordsetChangeComplete(
+ [in] EventReasonEnum reason,
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x0000000f)]
+ HRESULT WillMove(
+ [in] EventReasonEnum reason,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x00000010)]
+ HRESULT MoveComplete(
+ [in] EventReasonEnum reason,
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x00000011)]
+ HRESULT EndOfRecordset(
+ [in, out] VARIANT_BOOL *more_data,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x00000012)]
+ HRESULT FetchProgress(
+ [in] LONG progress,
+ [in] LONG max_progress,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+
+ [id(0x00000013)]
+ HRESULT FetchComplete(
+ [in] Error *error,
+ [in, out] EventStatusEnum *status,
+ [in] _Recordset *record_set);
+};
+
+[
+ uuid(00000538-0000-0010-8000-00aa006d2ea4),
+ odl,
+ hidden
+]
+interface ADODebugging : IUnknown
+{
+ HRESULT __stdcall IsGlobalDebugMode(
+ VARIANT_BOOL *debugging_on);
+
+ HRESULT __stdcall SetGlobalDebugMode(
+ IUnknown *debugger,
+ VARIANT_BOOL debugging_on);
+};
+
+[
+ uuid(00000516-0000-0010-8000-00aa006d2ea4),
+ odl,
+ restricted
+]
+interface ADOConnectionConstruction15 : IUnknown
+{
+ [propget]
+ HRESULT __stdcall DSO(
+ [out, retval] IUnknown **dso);
+
+ [propget]
+ HRESULT __stdcall Session(
+ [out, retval] IUnknown **session);
+
+ HRESULT __stdcall WrapDSOandSession(
+ [in] IUnknown *dso,
+ [in] IUnknown *session);
+};
+
+[
+ uuid(00000551-0000-0010-8000-00aa006d2ea4),
+ odl,
+ restricted
+]
+interface ADOConnectionConstruction : ADOConnectionConstruction15
+{
+};
+
+[
+ uuid(00000517-0000-0010-8000-00aa006d2ea4),
+ odl,
+ restricted
+]
+interface ADOCommandConstruction : IUnknown
+{
+ [propget]
+ HRESULT __stdcall OLEDBCommand(
+ [out, retval] IUnknown **command);
+
+ [propput]
+ HRESULT __stdcall OLEDBCommand(
+ [in] IUnknown *command);
+};
+
+[
+ uuid(00000283-0000-0010-8000-00aa006d2ea4),
+ odl,
+ restricted
+]
+interface ADORecordsetConstruction : IDispatch
+{
+ [propget]
+ HRESULT __stdcall Rowset(
+ [out, retval] IUnknown **row_set);
+
+ [propput]
+ HRESULT __stdcall Rowset(
+ [in] IUnknown *row_set);
+
+ [propget]
+ HRESULT __stdcall Chapter(
+ [out, retval] LONG *chapter);
+
+ [propput]
+ HRESULT __stdcall Chapter(
+ [in] LONG chapter);
+
+ [propget]
+ HRESULT __stdcall RowPosition(
+ [out, retval] IUnknown **row_pos);
+
+ [propput]
+ HRESULT __stdcall RowPosition(
+ [in] IUnknown *row_pos);
+};
+
+[
+ uuid(2a75196c-d9eb-4129-b803-931327f72d5c),
+ version(2.8)
+]
+library ADODB
+{
+ importlib("stdole2.tlb");
+
+ [
+ uuid(00000514-0000-0010-8000-00aa006d2ea4),
+ ]
+ coclass Connection
+ {
+ [default] interface _Connection;
+ [default, source] dispinterface ConnectionEvents;
+ };
+
+ [
+ uuid(00000507-0000-0010-8000-00aa006d2ea4),
+ ]
+ coclass Command
+ {
+ [default] interface _Command;
+ };
+
+ [
+ uuid(00000535-0000-0010-8000-00aa006d2ea4),
+ ]
+ coclass Recordset
+ {
+ [default] interface _Recordset;
+ [default, source] dispinterface RecordsetEvents;
+ };
+
+ [
+ uuid(0000050b-0000-0010-8000-00aa006d2ea4),
+ ]
+ coclass Parameter
+ {
+ [default] interface _Parameter;
+ };
+
+ [
+ uuid(00000560-0000-0010-8000-00aa006d2ea4),
+ ]
+ coclass Record
+ {
+ [default] interface _Record;
+ };
+
+ [
+ uuid(00000566-0000-0010-8000-00aa006d2ea4),
+ ]
+ coclass Stream
+ {
+ [default] interface _Stream;
+ };
+}
--
2.20.1
Dec. 6, 2019
[PATCH] dwrite/tests: Add some tests for reference objects.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/tests/font.c | 110 ++++++++++++++++++++++++++-------------
1 file changed, 75 insertions(+), 35 deletions(-)
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 5ab01465b7..a0d36e2f0b 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -7558,12 +7558,12 @@ static void test_CreateFontFaceReference(void)
static const WCHAR dummyW[] = {'d','u','m','m','y',0};
IDWriteFontFace3 *fontface, *fontface1;
IDWriteFontFaceReference *ref, *ref1;
+ IDWriteFontCollection1 *collection;
IDWriteFontFile *file, *file1;
IDWriteFactory3 *factory;
+ UINT32 index, count, i;
IDWriteFont3 *font3;
- IDWriteFont *font;
ULONG refcount;
- UINT32 index;
WCHAR *path;
HRESULT hr;
BOOL ret;
@@ -7672,47 +7672,87 @@ todo_wine
IDWriteFontFile_Release(file);
IDWriteFontFile_Release(file1);
- /* references returned from IDWriteFont3 */
- font = get_tahoma_instance((IDWriteFactory *)factory, DWRITE_FONT_STYLE_NORMAL);
- hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont3, (void**)&font3);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- IDWriteFont_Release(font);
+ /* References returned from IDWriteFont3/IDWriteFontFace3. */
+ hr = IDWriteFactory3_GetSystemFontCollection(factory, FALSE, &collection, FALSE);
+ ok(hr == S_OK, "Failed to get system collection, hr %#x.\n", hr);
- hr = IDWriteFont3_GetFontFaceReference(font3, &ref);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ count = IDWriteFontCollection1_GetFontFamilyCount(collection);
+ for (i = 0; i < count; i++)
+ {
+ IDWriteFontFamily1 *family;
+ UINT32 font_count, j;
- hr = IDWriteFont3_GetFontFaceReference(font3, &ref1);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- ok(ref != ref1, "got %p, %p\n", ref1, ref);
+ hr = IDWriteFontCollection1_GetFontFamily(collection, i, &family);
+ ok(hr == S_OK, "Failed to get family, hr %#x.\n", hr);
- IDWriteFontFaceReference_Release(ref);
- IDWriteFontFaceReference_Release(ref1);
+ font_count = IDWriteFontFamily1_GetFontCount(family);
- /* references returned from IDWriteFontFace3 */
- hr = IDWriteFont3_CreateFontFace(font3, &fontface);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ for (j = 0; j < font_count; j++)
+ {
+ IDWriteFontFaceReference1 *ref2;
- hr = IDWriteFontFace3_GetFontFaceReference(fontface, &ref);
-todo_wine
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IDWriteFontFamily1_GetFont(family, j, &font3);
+ ok(hr == S_OK, "Failed to get font, hr %#x.\n", hr);
- hr = IDWriteFontFace3_GetFontFaceReference(fontface, &ref1);
-todo_wine
- ok(hr == S_OK, "got 0x%08x\n", hr);
-if (hr == S_OK)
- ok(ref == ref1, "got %p, %p\n", ref1, ref);
+ hr = IDWriteFont3_GetFontFaceReference(font3, &ref);
+ ok(hr == S_OK, "Failed to get reference object, hr %#x.\n", hr);
-if (hr == S_OK) {
- hr = IDWriteFontFaceReference_CreateFontFace(ref, &fontface1);
- ok(hr == S_OK, "got 0x%08x\n", hr);
- ok(fontface1 == fontface, "got %p, %p\n", fontface1, fontface);
- IDWriteFontFace3_Release(fontface1);
+ hr = IDWriteFont3_GetFontFaceReference(font3, &ref1);
+ ok(hr == S_OK, "Failed to get reference object, hr %#x.\n", hr);
+ ok(ref != ref1, "Unexpected reference object %p, %p.\n", ref1, ref);
- IDWriteFontFaceReference_Release(ref);
- IDWriteFontFaceReference_Release(ref1);
-}
- IDWriteFontFace3_Release(fontface);
- IDWriteFont3_Release(font3);
+ hr = IDWriteFont3_CreateFontFace(font3, &fontface);
+ ok(hr == S_OK, "Failed to create a fontface, hr %#x.\n", hr);
+
+ /* Fonts present regular properties as axis values, for non-variable fonts too.
+ Normally it would include weight/width/slant/italic, but could also contain optical size axis. */
+ if (SUCCEEDED(hr = IDWriteFontFaceReference_QueryInterface(ref, &IID_IDWriteFontFaceReference1,
+ (void **)&ref2)))
+ {
+ UINT32 axis_count = IDWriteFontFaceReference1_GetFontAxisValueCount(ref2);
+ todo_wine
+ ok(axis_count > 0, "Unexpected axis value count.\n");
+ IDWriteFontFaceReference1_Release(ref2);
+ }
+
+ IDWriteFontFaceReference_Release(ref);
+ IDWriteFontFaceReference_Release(ref1);
+
+ hr = IDWriteFontFace3_GetFontFaceReference(fontface, &ref);
+ todo_wine
+ ok(hr == S_OK, "Failed to get a reference, hr %#x.\n", hr);
+
+ hr = IDWriteFontFace3_GetFontFaceReference(fontface, &ref1);
+ todo_wine
+ ok(hr == S_OK, "Failed to get a reference, hr %#x.\n", hr);
+ if (hr == S_OK)
+ ok(ref == ref1, "Unexpected reference %p, %p.\n", ref1, ref);
+
+ if (hr == S_OK) {
+ hr = IDWriteFontFaceReference_CreateFontFace(ref, &fontface1);
+ ok(hr == S_OK, "Failed to create fontface, hr %#x.\n", hr);
+ ok(fontface1 == fontface, "Unexpected fontface %p, %p.\n", fontface1, fontface);
+ IDWriteFontFace3_Release(fontface1);
+
+ if (SUCCEEDED(hr = IDWriteFontFaceReference_QueryInterface(ref, &IID_IDWriteFontFaceReference1,
+ (void **)&ref2)))
+ {
+ UINT32 axis_count = IDWriteFontFaceReference1_GetFontAxisValueCount(ref2);
+ ok(!axis_count, "Unexpected axis value count.\n");
+ IDWriteFontFaceReference1_Release(ref2);
+ }
+
+ IDWriteFontFaceReference_Release(ref);
+ IDWriteFontFaceReference_Release(ref1);
+ }
+ IDWriteFontFace3_Release(fontface);
+
+ IDWriteFont3_Release(font3);
+ }
+
+ IDWriteFontFamily1_Release(family);
+ }
+ IDWriteFontCollection1_Release(collection);
refcount = IDWriteFactory3_Release(factory);
ok(refcount == 0, "factory not released, %u\n", refcount);
--
2.24.0
Dec. 6, 2019
[PATCH] dwrite: Use IDWriteFactory7 for analyzer.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/analyzer.c | 22 +++++++++++-----------
dlls/dwrite/dwrite_private.h | 4 ++--
dlls/dwrite/main.c | 4 ++--
3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index 8db5cc709b..a418081d49 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -238,7 +238,7 @@ struct dwrite_fontfallback
{
IDWriteFontFallback1 IDWriteFontFallback1_iface;
LONG refcount;
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
IDWriteFontCollection1 *systemcollection;
struct fallback_mapping *mappings;
UINT32 mappings_count;
@@ -248,7 +248,7 @@ struct dwrite_fontfallback_builder
{
IDWriteFontFallbackBuilder IDWriteFontFallbackBuilder_iface;
LONG refcount;
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
struct fallback_mapping *mappings;
size_t size;
size_t count;
@@ -1956,7 +1956,7 @@ static ULONG WINAPI fontfallback_AddRef(IDWriteFontFallback1 *iface)
TRACE("%p.\n", iface);
- return IDWriteFactory5_AddRef(fallback->factory);
+ return IDWriteFactory7_AddRef(fallback->factory);
}
static ULONG WINAPI fontfallback_Release(IDWriteFontFallback1 *iface)
@@ -1965,7 +1965,7 @@ static ULONG WINAPI fontfallback_Release(IDWriteFontFallback1 *iface)
TRACE("%p.\n", fallback);
- return IDWriteFactory5_Release(fallback->factory);
+ return IDWriteFactory7_Release(fallback->factory);
}
static int compare_mapping_range(const void *a, const void *b)
@@ -2174,7 +2174,7 @@ static const IDWriteFontFallback1Vtbl fontfallbackvtbl =
fontfallback1_MapCharacters,
};
-HRESULT create_system_fontfallback(IDWriteFactory5 *factory, IDWriteFontFallback1 **ret)
+HRESULT create_system_fontfallback(IDWriteFactory7 *factory, IDWriteFontFallback1 **ret)
{
struct dwrite_fontfallback *fallback;
@@ -2188,7 +2188,7 @@ HRESULT create_system_fontfallback(IDWriteFactory5 *factory, IDWriteFontFallback
fallback->factory = factory;
fallback->mappings = (struct fallback_mapping *)fontfallback_neutral_data;
fallback->mappings_count = ARRAY_SIZE(fontfallback_neutral_data);
- IDWriteFactory5_GetSystemFontCollection(fallback->factory, FALSE, &fallback->systemcollection, FALSE);
+ IDWriteFactory5_GetSystemFontCollection((IDWriteFactory5 *)fallback->factory, FALSE, &fallback->systemcollection, FALSE);
*ret = &fallback->IDWriteFontFallback1_iface;
@@ -2221,7 +2221,7 @@ static ULONG WINAPI customfontfallback_Release(IDWriteFontFallback1 *iface)
if (!refcount)
{
- IDWriteFactory5_Release(fallback->factory);
+ IDWriteFactory7_Release(fallback->factory);
heap_free(fallback);
}
@@ -2310,7 +2310,7 @@ static ULONG WINAPI fontfallbackbuilder_Release(IDWriteFontFallbackBuilder *ifac
heap_free(mapping->locale);
}
- IDWriteFactory5_Release(fallbackbuilder->factory);
+ IDWriteFactory7_Release(fallbackbuilder->factory);
heap_free(fallbackbuilder->mappings);
heap_free(fallbackbuilder);
}
@@ -2383,7 +2383,7 @@ static HRESULT WINAPI fontfallbackbuilder_CreateFontFallback(IDWriteFontFallback
fallback->IDWriteFontFallback1_iface.lpVtbl = &customfontfallbackvtbl;
fallback->refcount = 1;
fallback->factory = fallbackbuilder->factory;
- IDWriteFactory5_AddRef(fallback->factory);
+ IDWriteFactory7_AddRef(fallback->factory);
*ret = (IDWriteFontFallback *)&fallback->IDWriteFontFallback1_iface;
return S_OK;
@@ -2399,7 +2399,7 @@ static const IDWriteFontFallbackBuilderVtbl fontfallbackbuildervtbl =
fontfallbackbuilder_CreateFontFallback,
};
-HRESULT create_fontfallback_builder(IDWriteFactory5 *factory, IDWriteFontFallbackBuilder **ret)
+HRESULT create_fontfallback_builder(IDWriteFactory7 *factory, IDWriteFontFallbackBuilder **ret)
{
struct dwrite_fontfallback_builder *builder;
@@ -2412,7 +2412,7 @@ HRESULT create_fontfallback_builder(IDWriteFactory5 *factory, IDWriteFontFallbac
builder->IDWriteFontFallbackBuilder_iface.lpVtbl = &fontfallbackbuildervtbl;
builder->refcount = 1;
builder->factory = factory;
- IDWriteFactory5_AddRef(builder->factory);
+ IDWriteFactory7_AddRef(builder->factory);
*ret = &builder->IDWriteFontFallbackBuilder_iface;
return S_OK;
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index c2aef6b77c..cc5c028fd2 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -258,9 +258,9 @@ extern HRESULT get_family_names_from_stream(IDWriteFontFileStream*,UINT32,DWRITE
extern HRESULT create_colorglyphenum(FLOAT,FLOAT,const DWRITE_GLYPH_RUN*,const DWRITE_GLYPH_RUN_DESCRIPTION*,DWRITE_MEASURING_MODE,
const DWRITE_MATRIX*,UINT32,IDWriteColorGlyphRunEnumerator**) DECLSPEC_HIDDEN;
extern BOOL lb_is_newline_char(WCHAR) DECLSPEC_HIDDEN;
-extern HRESULT create_system_fontfallback(IDWriteFactory5 *factory, IDWriteFontFallback1 **fallback) DECLSPEC_HIDDEN;
+extern HRESULT create_system_fontfallback(IDWriteFactory7 *factory, IDWriteFontFallback1 **fallback) DECLSPEC_HIDDEN;
extern void release_system_fontfallback(IDWriteFontFallback1 *fallback) DECLSPEC_HIDDEN;
-extern HRESULT create_fontfallback_builder(IDWriteFactory5*,IDWriteFontFallbackBuilder**) DECLSPEC_HIDDEN;
+extern HRESULT create_fontfallback_builder(IDWriteFactory7 *factory, IDWriteFontFallbackBuilder **builder) DECLSPEC_HIDDEN;
extern HRESULT create_matching_font(IDWriteFontCollection*,const WCHAR*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
IDWriteFont**) DECLSPEC_HIDDEN;
extern HRESULT create_fontfacereference(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index,
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 9c88ab6871..317a6cedaf 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1337,7 +1337,7 @@ static HRESULT WINAPI dwritefactory2_GetSystemFontFallback(IDWriteFactory7 *ifac
if (!factory->fallback)
{
- HRESULT hr = create_system_fontfallback((IDWriteFactory5 *)iface, &factory->fallback);
+ HRESULT hr = create_system_fontfallback(iface, &factory->fallback);
if (FAILED(hr))
return hr;
}
@@ -1352,7 +1352,7 @@ static HRESULT WINAPI dwritefactory2_CreateFontFallbackBuilder(IDWriteFactory7 *
{
TRACE("%p, %p.\n", iface, fallbackbuilder);
- return create_fontfallback_builder((IDWriteFactory5 *)iface, fallbackbuilder);
+ return create_fontfallback_builder(iface, fallbackbuilder);
}
static HRESULT WINAPI dwritefactory2_TranslateColorGlyphRun(IDWriteFactory7 *iface, FLOAT originX, FLOAT originY,
--
2.24.0
Dec. 6, 2019
[PATCH 2/2] winemac: Avoid some compiler warnings.
by Gijs Vermeulen
Signed-off-by: Gijs Vermeulen <gijsvrm(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_app.m | 9 ++++-----
dlls/winemac.drv/display.c | 7 +++----
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
index b5658eab08..87a73b6da9 100644
--- a/dlls/winemac.drv/cocoa_app.m
+++ b/dlls/winemac.drv/cocoa_app.m
@@ -769,9 +769,9 @@ - (BOOL) mode:(CGDisplayModeRef)mode1 matchesMode:(CGDisplayModeRef)mode2
if (CGDisplayModeGetHeight(mode1) != CGDisplayModeGetHeight(mode2)) return FALSE;
#if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- if (CGDisplayModeGetPixelWidth != NULL &&
+ if (&CGDisplayModeGetPixelWidth != NULL &&
CGDisplayModeGetPixelWidth(mode1) != CGDisplayModeGetPixelWidth(mode2)) return FALSE;
- if (CGDisplayModeGetPixelHeight != NULL &&
+ if (&CGDisplayModeGetPixelHeight != NULL &&
CGDisplayModeGetPixelHeight(mode1) != CGDisplayModeGetPixelHeight(mode2)) return FALSE;
#endif
@@ -801,9 +801,8 @@ - (NSArray*)modesMatchingMode:(CGDisplayModeRef)mode forDisplay:(CGDirectDisplay
NSDictionary* options = nil;
#if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- if (&kCGDisplayShowDuplicateLowResolutionModes != NULL)
- options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:TRUE]
- forKey:(NSString*)kCGDisplayShowDuplicateLowResolutionModes];
+ options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:TRUE]
+ forKey:(NSString*)kCGDisplayShowDuplicateLowResolutionModes];
#endif
NSArray *modes = [(NSArray*)CGDisplayCopyAllDisplayModes(displayID, (CFDictionaryRef)options) autorelease];
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index cc5e9beaff..bafdb42589 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -268,7 +268,7 @@ static BOOL write_display_settings(HKEY parent_hkey, CGDirectDisplayID displayID
goto fail;
#if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- if (CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL)
+ if (&CGDisplayModeGetPixelWidth != NULL && &CGDisplayModeGetPixelHeight != NULL)
{
val = CGDisplayModeGetPixelWidth(display_mode);
if (RegSetValueExA(display_hkey, "PixelWidth", 0, REG_DWORD, (const BYTE*)&val, sizeof(val)))
@@ -456,7 +456,7 @@ static BOOL display_mode_matches_descriptor(CGDisplayModeRef mode, const struct
return FALSE;
#if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- if (CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL)
+ if (&CGDisplayModeGetPixelWidth != NULL && &CGDisplayModeGetPixelHeight != NULL)
{
if (CGDisplayModeGetPixelWidth(mode) != desc->pixel_width ||
CGDisplayModeGetPixelHeight(mode) != desc->pixel_height)
@@ -616,8 +616,7 @@ static CFArrayRef copy_display_modes(CGDirectDisplayID display)
CFArrayRef modes = NULL;
#if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
- if (&kCGDisplayShowDuplicateLowResolutionModes != NULL &&
- CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL)
+ if (&CGDisplayModeGetPixelWidth != NULL && &CGDisplayModeGetPixelHeight != NULL)
{
CFDictionaryRef options;
struct display_mode_descriptor* desc;
--
2.24.0
Dec. 6, 2019
[PATCH 1/2] secur32: Avoid compiler warning.
by Gijs Vermeulen
Signed-off-by: Gijs Vermeulen <gijsvrm(a)codeweavers.com>
---
dlls/secur32/schannel_macosx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/secur32/schannel_macosx.c b/dlls/secur32/schannel_macosx.c
index 050e8c5cce..d06267773a 100644
--- a/dlls/secur32/schannel_macosx.c
+++ b/dlls/secur32/schannel_macosx.c
@@ -1202,7 +1202,7 @@ BOOL schan_imp_init(void)
supported_protocols = SP_PROT_SSL2_CLIENT | SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_0_CLIENT;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
- if(SSLGetProtocolVersionMax != NULL) {
+ if(&SSLGetProtocolVersionMax != NULL) {
SSLProtocol max_protocol;
SSLContextRef ctx;
OSStatus status;
--
2.24.0
Dec. 6, 2019
[website] German translation for release 4.21
by Julian Rüger
Signed-off-by: Julian Rüger <jr98(a)gmx.net>
Dec. 6, 2019
[website] German translation for release 4.0.3
by Julian Rüger
Signed-off-by: Julian Rüger <jr98(a)gmx.net>
Dec. 6, 2019
[website] German translation for release 4.20
by Julian Rüger
Signed-off-by: Julian Rüger <jr98(a)gmx.net>
Dec. 6, 2019
[PATCH 2/2] oleaut32/typelib: Implement DeleteImplType().
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/oleaut32/tests/typelib.c | 98 +++++++++++++++++++++++++++++++++++
dlls/oleaut32/typelib.c | 21 +++++++-
2 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c
index 47faad7763..053011d4be 100644
--- a/dlls/oleaut32/tests/typelib.c
+++ b/dlls/oleaut32/tests/typelib.c
@@ -6446,6 +6446,103 @@ static void test_dep(void) {
DeleteFileW(filenameW);
}
+static void test_DeleteImplType(void)
+{
+ static OLECHAR interface1W[] = L"interface1";
+ HREFTYPE hreftype, hreftype2;
+ ICreateTypeInfo2 *createti2;
+ ICreateTypeInfo *createti;
+ ICreateTypeLib2 *createtl;
+ WCHAR filenameW[MAX_PATH];
+ ITypeInfo *dispti, *ti;
+ ITypeLib *stdole, *tl;
+ TYPEATTR *typeattr;
+ HRESULT hr;
+ int flags;
+
+ hr = LoadTypeLib(L"stdole2.tlb", &stdole);
+ ok(hr == S_OK, "Failed to load stdole2, hr %#x.\n", hr);
+
+ hr = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispti);
+ ok(hr == S_OK, "Failed to get IDispatch typeinfo, hr %#x.\n", hr);
+
+ GetTempFileNameW(L".", L"tlb", 0, filenameW);
+
+ hr = CreateTypeLib2(SYS_WIN32, filenameW, &createtl);
+ ok(hr == S_OK, "Failed to create instance, hr %#x.\n", hr);
+
+ hr = ICreateTypeLib2_CreateTypeInfo(createtl, interface1W, TKIND_INTERFACE, &createti);
+ ok(hr == S_OK, "Failed to create instance, hr %#x.\n", hr);
+ hr = ICreateTypeInfo_QueryInterface(createti, &IID_ICreateTypeInfo2, (void **)&createti2);
+ ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
+ ICreateTypeInfo_Release(createti);
+
+ hr = ICreateTypeInfo2_AddRefTypeInfo(createti2, dispti, &hreftype);
+ ok(hr == S_OK, "Failed to add referenced typeinfo, hr %#x.\n", hr);
+
+ hr = ICreateTypeInfo2_QueryInterface(createti2, &IID_ITypeInfo, (void **)&ti);
+ ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
+
+ hr = ITypeInfo_GetTypeAttr(ti, &typeattr);
+ ok(hr == S_OK, "Failed to get type attr, hr %#x.\n", hr);
+ ok(!(typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE), "Unexpected type flags %#x.\n", typeattr->wTypeFlags);
+ ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+ hr = ICreateTypeInfo2_AddImplType(createti2, 0, hreftype);
+ ok(hr == S_OK, "Failed to add impl type, hr %#x.\n", hr);
+
+ hr = ITypeInfo_GetTypeAttr(ti, &typeattr);
+ ok(hr == S_OK, "Failed to get type attr, hr %#x.\n", hr);
+ ok(typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE, "Unexpected type flags %#x.\n", typeattr->wTypeFlags);
+ ok(typeattr->cImplTypes == 1, "Unexpected cImplTypes value.\n");
+ ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+ /* Delete impltype, check flags. */
+ hr = ICreateTypeInfo2_DeleteImplType(createti2, 0);
+ ok(hr == S_OK, "Failed to delete impl type, hr %#x.\n", hr);
+
+ hr = ICreateTypeInfo2_DeleteImplType(createti2, 0);
+ ok(hr == TYPE_E_ELEMENTNOTFOUND, "Unexpected hr %#x.\n", hr);
+
+ hr = ITypeInfo_GetTypeAttr(ti, &typeattr);
+ ok(hr == S_OK, "Failed to get type attr, hr %#x.\n", hr);
+ ok(typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE, "Unexpected type flags %#x.\n", typeattr->wTypeFlags);
+ ok(!typeattr->cImplTypes, "Unexpected cImplTypes value.\n");
+ ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+ hr = ITypeInfo_GetImplTypeFlags(ti, 0, &flags);
+ ok(hr == TYPE_E_ELEMENTNOTFOUND, "Unexpected hr %#x.\n", hr);
+
+ hr = ITypeInfo_GetRefTypeOfImplType(ti, 0, &hreftype2);
+ ok(hr == TYPE_E_ELEMENTNOTFOUND, "Unexpected hr %#x.\n", hr);
+
+ hr = ICreateTypeLib2_SaveAllChanges(createtl);
+ ok(hr == S_OK, "Failed to save changes, hr %#x.\n", hr);
+ ICreateTypeLib2_Release(createtl);
+ ITypeInfo_Release(ti);
+ ICreateTypeInfo2_Release(createti2);
+
+ /* Load and check typeinfo. */
+ hr = LoadTypeLibEx(filenameW, REGKIND_NONE, &tl);
+ ok(hr == S_OK, "Failed to load typelib, hr %#x.\n", hr);
+
+ hr = ITypeLib_GetTypeInfo(tl, 0, &ti);
+ ok(hr == S_OK, "Failed to get typeinfo, hr %#x.\n", hr);
+ hr = ITypeInfo_GetTypeAttr(ti, &typeattr);
+ ok(hr == S_OK, "Failed to get type attr, hr %#x.\n", hr);
+ ok(typeattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE, "Unexpected type flags %#x.\n", typeattr->wTypeFlags);
+ ok(!typeattr->cImplTypes, "Unexpected cImplTypes value.\n");
+ ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+ ITypeInfo_Release(ti);
+
+ ITypeLib_Release(tl);
+
+ ITypeLib_Release(stdole);
+ ITypeInfo_Release(dispti);
+
+ DeleteFileW(filenameW);
+}
+
START_TEST(typelib)
{
const char *filename;
@@ -6486,4 +6583,5 @@ START_TEST(typelib)
test_GetLibAttr();
test_stub();
test_dep();
+ test_DeleteImplType();
}
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 6d96cc5fbe..e629ed51d5 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -11356,8 +11356,25 @@ static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
UINT index)
{
ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
- FIXME("%p %u - stub\n", This, index);
- return E_NOTIMPL;
+ int i;
+
+ TRACE("%p %u\n", This, index);
+
+ if (index >= This->typeattr.cImplTypes)
+ return TYPE_E_ELEMENTNOTFOUND;
+
+ TLB_FreeCustData(&This->impltypes[index].custdata_list);
+ --This->typeattr.cImplTypes;
+
+ if (index < This->typeattr.cImplTypes)
+ {
+ memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
+ sizeof(*This->impltypes));
+ for (i = index; i < This->typeattr.cImplTypes; ++i)
+ TLB_relink_custdata(&This->impltypes[i].custdata_list);
+ }
+
+ return S_OK;
}
static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
--
2.24.0
Dec. 6, 2019
[PATCH 1/2] oleaut32/typelib: Add a helper to update custom data lists on reallocation.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/oleaut32/typelib.c | 45 +++++++++++++++++------------------------
1 file changed, 18 insertions(+), 27 deletions(-)
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 1971a41570..6d96cc5fbe 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -1871,6 +1871,18 @@ static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VA
return VariantCopy(&cust_data->data, var);
}
+/* Used to update list pointers after list itself was moved. */
+static void TLB_relink_custdata(struct list *custdata_list)
+{
+ if (custdata_list->prev == custdata_list->next)
+ list_init(custdata_list);
+ else
+ {
+ custdata_list->prev->next = custdata_list;
+ custdata_list->next->prev = custdata_list;
+ }
+}
+
static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
{
TLBString *str;
@@ -10806,15 +10818,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
/* move custdata lists to the new memory location */
for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
- if(index != i){
- TLBFuncDesc *fd = &This->funcdescs[i];
- if(fd->custdata_list.prev == fd->custdata_list.next)
- list_init(&fd->custdata_list);
- else{
- fd->custdata_list.prev->next = &fd->custdata_list;
- fd->custdata_list.next->prev = &fd->custdata_list;
- }
- }
+ if(index != i)
+ TLB_relink_custdata(&This->funcdescs[i].custdata_list);
}
} else
func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
@@ -10875,15 +10880,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
/* move custdata lists to the new memory location */
for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
- if(index != i){
- TLBImplType *it = &This->impltypes[i];
- if(it->custdata_list.prev == it->custdata_list.next)
- list_init(&it->custdata_list);
- else{
- it->custdata_list.prev->next = &it->custdata_list;
- it->custdata_list.next->prev = &it->custdata_list;
- }
- }
+ if(index != i)
+ TLB_relink_custdata(&This->impltypes[i].custdata_list);
}
} else
impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
@@ -10975,15 +10973,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
/* move custdata lists to the new memory location */
for(i = 0; i < This->typeattr.cVars + 1; ++i){
- if(index != i){
- TLBVarDesc *var = &This->vardescs[i];
- if(var->custdata_list.prev == var->custdata_list.next)
- list_init(&var->custdata_list);
- else{
- var->custdata_list.prev->next = &var->custdata_list;
- var->custdata_list.next->prev = &var->custdata_list;
- }
- }
+ if(index != i)
+ TLB_relink_custdata(&This->vardescs[i].custdata_list);
}
} else
var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
--
2.24.0
Dec. 6, 2019
Re: [PATCH] kernelbase: Fix GlobalMemoryStatusEx regression.
by Zhiyi Zhang
> status->ullTotalPageFile = (perf_info.TotalCommitLimit + 1) * (ULONGLONG) basic_info.PageSize; /* Titan Quest refuses to run if TotalPageFile <= TotalPhys */
> + status->ullAvailPageFile = (status->ullTotalPageFile - perf_info.TotalCommittedPages - perf_info.AvailablePages) * (ULONGLONG) basic_info.PageSize;
ullAvailPageFile got basic_info.PageSize multiplied twice, pretty sure that's wrong.
On 12/6/19 12:29 PM, hari.mail wrote:
> Empty Message
Dec. 6, 2019
[PATCH vkd3d] vkd3d: Remove redundant GetCopyableFootprints() resource size alignment checks.
by Conor McCarthy
The alignments are now checked in d3d12_resource_validate_desc().
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
libs/vkd3d/device.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 89d8aea..f652765 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -3497,13 +3497,6 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device *i
return;
}
- if (align(desc->Width, format->block_width) != desc->Width
- || align(desc->Height, format->block_height) != desc->Height)
- {
- WARN("Resource size (%"PRIu64"x%u) not aligned to format block size.\n", desc->Width, desc->Height);
- return;
- }
-
offset = 0;
total = 0;
for (i = 0; i < sub_resource_count; ++i)
--
2.24.0
Dec. 6, 2019
Re: [PATCH v2 1/4] strmbase: Correctly implement IVideoWindow::NotifyOwnerMessage().
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=61455
Your paranoid android.
=== w1064v1809_ja (32 bit report) ===
quartz:
videorenderer.c:726: Test failed: Got hr 0x40237.
Dec. 6, 2019
[PATCH] kernel32/tests: Allow for differing fpu_cw returned on Windows XP.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/kernel32/tests/thread.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
index 9a8ad9151c..beec84e044 100644
--- a/dlls/kernel32/tests/thread.c
+++ b/dlls/kernel32/tests/thread.c
@@ -1745,14 +1745,16 @@ static unsigned int get_thread_fpu_cw( unsigned long *fpu_cw )
static void test_thread_fpu_cw(void)
{
- static const struct { unsigned int cw; unsigned long fpu_cw; } expected_cw[6] =
+ static const struct {
+ unsigned int cw; unsigned long fpu_cw; unsigned long fpu_cw_alt;
+ } expected_cw[6] =
{
#ifdef __i386__
{ _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
{ _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
- { _EM_INEXACT | _RC_CHOP | _PC_24, MAKELONG( 0xc60, 0x7000 ) },
+ { _EM_INEXACT | _RC_CHOP | _PC_24, MAKELONG( 0xc60, 0x7000 ), MAKELONG( 0xc60, 0x1f80 ) },
{ _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
- { _EM_INEXACT | _RC_CHOP | _PC_24, MAKELONG( 0xc60, 0x7000 ) },
+ { _EM_INEXACT | _RC_CHOP | _PC_24, MAKELONG( 0xc60, 0x7000 ), MAKELONG( 0xc60, 0x1f80 ) },
{ _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) }
#elif defined(__x86_64__)
{ _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
@@ -1788,7 +1790,9 @@ static void test_thread_fpu_cw(void)
cw = _control87( 0, 0 );
fpu_cw = get_fpu_cw();
ok(cw == expected_cw[2].cw, "expected %#x got %#x\n", expected_cw[2].cw, cw);
- ok(fpu_cw == expected_cw[2].fpu_cw, "expected %#lx got %#lx\n", expected_cw[2].fpu_cw, fpu_cw);
+ ok(fpu_cw == expected_cw[2].fpu_cw ||
+ broken(expected_cw[2].fpu_cw_alt != 0 && fpu_cw == expected_cw[2].fpu_cw_alt),
+ "expected %#lx got %#lx\n", expected_cw[2].fpu_cw, fpu_cw);
cw = get_thread_fpu_cw( &fpu_cw );
ok(cw == expected_cw[3].cw, "expected %#x got %#x\n", expected_cw[3].cw, cw);
@@ -1797,7 +1801,9 @@ static void test_thread_fpu_cw(void)
cw = _control87( 0, 0 );
fpu_cw = get_fpu_cw();
ok(cw == expected_cw[4].cw, "expected %#x got %#x\n", expected_cw[4].cw, cw);
- ok(fpu_cw == expected_cw[4].fpu_cw, "expected %#lx got %#lx\n", expected_cw[4].fpu_cw, fpu_cw);
+ ok(fpu_cw == expected_cw[4].fpu_cw ||
+ broken(expected_cw[4].fpu_cw_alt != 0 && fpu_cw == expected_cw[4].fpu_cw_alt),
+ "expected %#lx got %#lx\n", expected_cw[4].fpu_cw, fpu_cw);
_control87( initial_cw, _MCW_EM | _MCW_RC | _MCW_PC );
cw = _control87( 0, 0 );
--
2.23.0
Dec. 6, 2019
[PATCH v2 4/4] strmbase: Create the video window with the correct styles.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/videorenderer.c | 8 ++++----
dlls/quartz/tests/vmr7.c | 8 ++++----
dlls/quartz/tests/vmr9.c | 8 ++++----
dlls/strmbase/window.c | 3 ++-
4 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index b2202d7ae7..2b4b166958 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -1391,11 +1391,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1414,10 +1414,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index fd4c69a441..224ae3c717 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1525,11 +1525,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1548,10 +1548,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 5d5c7a4756..fd6901d211 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1525,11 +1525,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1548,10 +1548,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/strmbase/window.c b/dlls/strmbase/window.c
index 04132aaab1..07a12eca26 100644
--- a/dlls/strmbase/window.c
+++ b/dlls/strmbase/window.c
@@ -118,7 +118,8 @@ HRESULT WINAPI BaseWindowImpl_PrepareWindow(BaseWindow *This)
return E_FAIL;
}
- This->hWnd = CreateWindowExW(0, class_nameW, windownameW, WS_SIZEBOX,
+ This->hWnd = CreateWindowExW(0, class_nameW, windownameW,
+ WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, NULL);
--
2.24.0
Dec. 6, 2019
[PATCH v2 3/4] quartz/tests: Port IVideoWindow tests to the VMR.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/vmr7.c | 790 ++++++++++++++++++++++++++++++++++++++
dlls/quartz/tests/vmr9.c | 807 +++++++++++++++++++++++++++++++++++++++
2 files changed, 1597 insertions(+)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index 98dfd4551b..fd4c69a441 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1461,6 +1461,795 @@ static void test_overlay(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+ int diff = 200;
+ DWORD time;
+ MSG msg;
+
+ time = GetTickCount() + diff;
+ while (diff > 0)
+ {
+ if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
+ break;
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ DispatchMessageA(&msg);
+ diff = time - GetTickCount();
+ }
+}
+
+static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (winetest_debug > 1)
+ trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd, msg, wparam, lparam);
+
+ if (wparam == 0xdeadbeef)
+ return 0;
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+static void test_video_window_caption(IVideoWindow *window, HWND hwnd)
+{
+ WCHAR text[50];
+ BSTR caption;
+ HRESULT hr;
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text));
+
+ caption = SysAllocString(L"foo");
+ hr = IVideoWindow_put_Caption(window, caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ SysFreeString(caption);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"foo"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"foo"), "Got caption %s.\n", wine_dbgstr_w(text));
+}
+
+static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG style;
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_HSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_VSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MAXIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MINIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowStyle(window, style & ~WS_CLIPCHILDREN);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyleEx(window, style | WS_EX_TRANSPARENT);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+}
+
+static BOOL CALLBACK top_window_cb(HWND hwnd, LPARAM ctx)
+{
+ DWORD pid;
+ GetWindowThreadProcessId(hwnd, &pid);
+ if (pid == GetCurrentProcessId() && (GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE))
+ {
+ *(HWND *)ctx = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static HWND get_top_window(void)
+{
+ HWND hwnd;
+ EnumWindows(top_window_cb, (LPARAM)&hwnd);
+ return hwnd;
+}
+
+static void test_video_window_state(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG state;
+ HWND top;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_put_WindowState(window, SW_MINIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MINIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(IsIconic(hwnd), "Window should be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_MAXIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MAXIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should be minimized.\n");
+ ok(IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowState(window, SW_HIDE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_SetWindowForeground(window, TRUE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == our_hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == our_hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+}
+
+static void test_video_window_position(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ LONG left, width, top, height, expect_width, expect_height;
+ RECT rect = {0, 0, 600, 400};
+ HWND top_hwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ AdjustWindowRect(&rect, GetWindowLongA(hwnd, GWL_STYLE), FALSE);
+ expect_width = rect.right - rect.left;
+ expect_height = rect.bottom - rect.top;
+
+ hr = IVideoWindow_put_Left(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_Top(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 0, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Left(window, 10);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Height(window, 200);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 200, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ ok(height == 200, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 200, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_SetWindowPosition(window, 100, 200, 300, 400);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 200, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 300, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 400, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ ok(top == 200, "Got top %d.\n", top);
+ ok(width == 300, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 100, "Got window left %d.\n", rect.left);
+ ok(rect.top == 200, "Got window top %d.\n", rect.top);
+ ok(rect.right == 400, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 600, "Got window bottom %d.\n", rect.bottom);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+}
+
+static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HWND parent, top_hwnd;
+ LONG style, state;
+ OAHWND oahwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == our_hwnd, "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok((style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+
+ ShowWindow(our_hwnd, SW_HIDE);
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == hwnd, "Got top window %p.\n", top_hwnd);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OATRUE, "Got state %d.\n", state);
+}
+
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
+static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ struct notify_message_params params;
+ unsigned int i;
+ OAHWND oahwnd;
+ HANDLE thread;
+ HRESULT hr;
+ BOOL ret;
+ MSG msg;
+
+ static UINT drain_tests[] =
+ {
+ WM_MOUSEACTIVATE,
+ WM_NCLBUTTONDOWN,
+ WM_NCLBUTTONUP,
+ WM_NCLBUTTONDBLCLK,
+ WM_NCRBUTTONDOWN,
+ WM_NCRBUTTONUP,
+ WM_NCRBUTTONDBLCLK,
+ WM_NCMBUTTONDOWN,
+ WM_NCMBUTTONUP,
+ WM_NCMBUTTONDBLCLK,
+ WM_KEYDOWN,
+ WM_KEYUP,
+ WM_MOUSEMOVE,
+ WM_LBUTTONDOWN,
+ WM_LBUTTONUP,
+ WM_LBUTTONDBLCLK,
+ WM_RBUTTONDOWN,
+ WM_RBUTTONUP,
+ WM_RBUTTONDBLCLK,
+ WM_MBUTTONDOWN,
+ WM_MBUTTONUP,
+ WM_MBUTTONDBLCLK,
+ };
+
+ flush_events();
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got window %#lx.\n", oahwnd);
+
+ hr = IVideoWindow_put_MessageDrain(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got window %#lx.\n", oahwnd);
+
+ for (i = 0; i < ARRAY_SIZE(drain_tests); ++i)
+ {
+ SendMessageA(hwnd, drain_tests[i], 0xdeadbeef, 0);
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(ret, "Expected a message.\n");
+ ok(msg.hwnd == our_hwnd, "Got hwnd %p.\n", msg.hwnd);
+ ok(msg.message == drain_tests[i], "Got message %#x.\n", msg.message);
+ ok(msg.wParam == 0xdeadbeef, "Got wparam %#lx.\n", msg.wParam);
+ ok(!msg.lParam, "Got lparam %#lx.\n", msg.lParam);
+ DispatchMessageA(&msg);
+
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(!ret, "Got unexpected message %#x.\n", msg.message);
+ }
+
+ hr = IVideoWindow_put_MessageDrain(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ flush_events();
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SYSCOLORCHANGE, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
+ (WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ ok(!WaitForSingleObject(thread, 1000), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 1000), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+}
+
+static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *graph, HWND hwnd)
+{
+ IMediaControl *control;
+ HRESULT hr;
+ LONG l;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_AutoShow(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OAFALSE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+}
+
+static void test_video_window(void)
+{
+ ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props;
+ VIDEOINFOHEADER vih =
+ {
+ .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+ .bmiHeader.biBitCount = 32,
+ .bmiHeader.biWidth = 600,
+ .bmiHeader.biHeight = 400,
+ .bmiHeader.biPlanes = 1,
+ .bmiHeader.biCompression = BI_RGB,
+ };
+ AM_MEDIA_TYPE req_mt =
+ {
+ .majortype = MEDIATYPE_Video,
+ .subtype = MEDIASUBTYPE_RGB32,
+ .formattype = FORMAT_VideoInfo,
+ .cbFormat = sizeof(vih),
+ .pbFormat = (BYTE *)&vih,
+ };
+ IFilterGraph2 *graph = create_graph();
+ WNDCLASSA window_class = {0};
+ struct testfilter source;
+ IMemAllocator *allocator;
+ IMediaControl *control;
+ LONG width, height, l;
+ IVideoWindow *window;
+ IMemInputPin *input;
+ IBaseFilter *filter;
+ HWND hwnd, our_hwnd;
+ IOverlay *overlay;
+ BSTR caption;
+ HRESULT hr;
+ DWORD tid;
+ ULONG ref;
+ IPin *pin;
+ RECT rect;
+
+ window_class.lpszClassName = "wine_test_class";
+ window_class.lpfnWndProc = window_proc;
+ RegisterClassA(&window_class);
+ our_hwnd = CreateWindowA("wine_test_class", "test window", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
+ 100, 200, 300, 400, NULL, NULL, NULL, NULL);
+ flush_events();
+
+ filter = create_vmr7(0);
+ flush_events();
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
+ IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
+
+ hr = IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IOverlay_GetWindowHandle(overlay, &hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (winetest_debug > 1) trace("ours %p, theirs %p\n", our_hwnd, hwnd);
+ GetWindowRect(hwnd, &rect);
+
+ tid = GetWindowThreadProcessId(hwnd, NULL);
+ ok(tid == GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid);
+
+ hr = IBaseFilter_QueryInterface(filter, &IID_IVideoWindow, (void **)&window);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ testfilter_init(&source);
+ IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, filter, NULL);
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ if (hr == VFW_E_TYPE_NOT_ACCEPTED) /* w7u */
+ {
+ req_mt.subtype = MEDIASUBTYPE_RGB24;
+ vih.bmiHeader.biBitCount = 24;
+ req_props.cbBuffer = 32 * 16 * 3;
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ }
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMemInputPin_GetAllocator(input, &allocator);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
+ hr = IMemAllocator_Commit(allocator);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMemAllocator_Release(allocator);
+ }
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ test_video_window_caption(window, hwnd);
+ test_video_window_style(window, hwnd, our_hwnd);
+ test_video_window_state(window, hwnd, our_hwnd);
+ test_video_window_position(window, hwnd, our_hwnd);
+ test_video_window_autoshow(window, graph, hwnd);
+ test_video_window_owner(window, hwnd, our_hwnd);
+ test_video_window_messages(window, hwnd, our_hwnd);
+
+ hr = IVideoWindow_put_FullScreenMode(window, OATRUE);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_get_FullScreenMode(window, &l);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_Release(graph);
+ IVideoWindow_Release(window);
+ IOverlay_Release(overlay);
+ IMemInputPin_Release(input);
+ IPin_Release(pin);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ DestroyWindow(our_hwnd);
+}
+
START_TEST(vmr7)
{
CoInitialize(NULL);
@@ -1476,6 +2265,7 @@ START_TEST(vmr7)
test_unconnected_filter_state();
test_connect_pin();
test_overlay();
+ test_video_window();
CoUninitialize();
}
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 70b100544c..5d5c7a4756 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1461,6 +1461,812 @@ static void test_overlay(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+ int diff = 200;
+ DWORD time;
+ MSG msg;
+
+ time = GetTickCount() + diff;
+ while (diff > 0)
+ {
+ if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
+ break;
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ DispatchMessageA(&msg);
+ diff = time - GetTickCount();
+ }
+}
+
+static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (winetest_debug > 1)
+ trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd, msg, wparam, lparam);
+
+ if (wparam == 0xdeadbeef)
+ return 0;
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+static void test_video_window_caption(IVideoWindow *window, HWND hwnd)
+{
+ WCHAR text[50];
+ BSTR caption;
+ HRESULT hr;
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text));
+
+ caption = SysAllocString(L"foo");
+ hr = IVideoWindow_put_Caption(window, caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ SysFreeString(caption);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"foo"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"foo"), "Got caption %s.\n", wine_dbgstr_w(text));
+}
+
+static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG style;
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_HSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_VSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MAXIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MINIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowStyle(window, style & ~WS_CLIPCHILDREN);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyleEx(window, style | WS_EX_TRANSPARENT);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+}
+
+static BOOL CALLBACK top_window_cb(HWND hwnd, LPARAM ctx)
+{
+ DWORD pid;
+ GetWindowThreadProcessId(hwnd, &pid);
+ if (pid == GetCurrentProcessId() && (GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE))
+ {
+ *(HWND *)ctx = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static HWND get_top_window(void)
+{
+ HWND hwnd;
+ EnumWindows(top_window_cb, (LPARAM)&hwnd);
+ return hwnd;
+}
+
+static void test_video_window_state(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG state;
+ HWND top;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_put_WindowState(window, SW_MINIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MINIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(IsIconic(hwnd), "Window should be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_MAXIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MAXIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should be minimized.\n");
+ ok(IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowState(window, SW_HIDE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_SetWindowForeground(window, TRUE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == our_hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == our_hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+}
+
+static void test_video_window_position(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ LONG left, width, top, height, expect_width, expect_height;
+ RECT rect = {0, 0, 600, 400};
+ HWND top_hwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ AdjustWindowRect(&rect, GetWindowLongA(hwnd, GWL_STYLE), FALSE);
+ expect_width = rect.right - rect.left;
+ expect_height = rect.bottom - rect.top;
+
+ hr = IVideoWindow_put_Left(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_Top(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 0, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Left(window, 10);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Height(window, 200);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 200, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ ok(height == 200, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 200, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_SetWindowPosition(window, 100, 200, 300, 400);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 200, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 300, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 400, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ ok(top == 200, "Got top %d.\n", top);
+ ok(width == 300, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 100, "Got window left %d.\n", rect.left);
+ ok(rect.top == 200, "Got window top %d.\n", rect.top);
+ ok(rect.right == 400, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 600, "Got window bottom %d.\n", rect.bottom);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+}
+
+static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HWND parent, top_hwnd;
+ LONG style, state;
+ OAHWND oahwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == our_hwnd, "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok((style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+
+ ShowWindow(our_hwnd, SW_HIDE);
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == hwnd, "Got top window %p.\n", top_hwnd);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OATRUE, "Got state %d.\n", state);
+}
+
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
+static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ struct notify_message_params params;
+ unsigned int i;
+ OAHWND oahwnd;
+ HANDLE thread;
+ HRESULT hr;
+ BOOL ret;
+ MSG msg;
+
+ static UINT drain_tests[] =
+ {
+ WM_MOUSEACTIVATE,
+ WM_NCLBUTTONDOWN,
+ WM_NCLBUTTONUP,
+ WM_NCLBUTTONDBLCLK,
+ WM_NCRBUTTONDOWN,
+ WM_NCRBUTTONUP,
+ WM_NCRBUTTONDBLCLK,
+ WM_NCMBUTTONDOWN,
+ WM_NCMBUTTONUP,
+ WM_NCMBUTTONDBLCLK,
+ WM_KEYDOWN,
+ WM_KEYUP,
+ WM_MOUSEMOVE,
+ WM_LBUTTONDOWN,
+ WM_LBUTTONUP,
+ WM_LBUTTONDBLCLK,
+ WM_RBUTTONDOWN,
+ WM_RBUTTONUP,
+ WM_RBUTTONDBLCLK,
+ WM_MBUTTONDOWN,
+ WM_MBUTTONUP,
+ WM_MBUTTONDBLCLK,
+ };
+
+ flush_events();
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got window %#lx.\n", oahwnd);
+
+ hr = IVideoWindow_put_MessageDrain(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got window %#lx.\n", oahwnd);
+
+ for (i = 0; i < ARRAY_SIZE(drain_tests); ++i)
+ {
+ SendMessageA(hwnd, drain_tests[i], 0xdeadbeef, 0);
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(ret, "Expected a message.\n");
+ ok(msg.hwnd == our_hwnd, "Got hwnd %p.\n", msg.hwnd);
+ ok(msg.message == drain_tests[i], "Got message %#x.\n", msg.message);
+ ok(msg.wParam == 0xdeadbeef, "Got wparam %#lx.\n", msg.wParam);
+ ok(!msg.lParam, "Got lparam %#lx.\n", msg.lParam);
+ DispatchMessageA(&msg);
+
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(!ret, "Got unexpected message %#x.\n", msg.message);
+ }
+
+ hr = IVideoWindow_put_MessageDrain(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ flush_events();
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SYSCOLORCHANGE, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
+ (WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ ok(!WaitForSingleObject(thread, 1000), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 1000), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+}
+
+static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *graph, HWND hwnd)
+{
+ IMediaControl *control;
+ HRESULT hr;
+ LONG l;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_AutoShow(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OAFALSE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+}
+
+static void test_video_window(void)
+{
+ ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props;
+ VIDEOINFOHEADER vih =
+ {
+ .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+ .bmiHeader.biBitCount = 32,
+ .bmiHeader.biWidth = 600,
+ .bmiHeader.biHeight = 400,
+ .bmiHeader.biPlanes = 1,
+ .bmiHeader.biCompression = BI_RGB,
+ };
+ AM_MEDIA_TYPE req_mt =
+ {
+ .majortype = MEDIATYPE_Video,
+ .subtype = MEDIASUBTYPE_RGB32,
+ .formattype = FORMAT_VideoInfo,
+ .cbFormat = sizeof(vih),
+ .pbFormat = (BYTE *)&vih,
+ };
+ IFilterGraph2 *graph = create_graph();
+ WNDCLASSA window_class = {0};
+ struct testfilter source;
+ IMemAllocator *allocator;
+ MONITORINFO monitorinfo;
+ IMediaControl *control;
+ LONG width, height, l;
+ IVideoWindow *window;
+ IMemInputPin *input;
+ IBaseFilter *filter;
+ HWND hwnd, our_hwnd;
+ IOverlay *overlay;
+ BSTR caption;
+ HRESULT hr;
+ DWORD tid;
+ ULONG ref;
+ IPin *pin;
+ RECT rect;
+
+ window_class.lpszClassName = "wine_test_class";
+ window_class.lpfnWndProc = window_proc;
+ RegisterClassA(&window_class);
+ our_hwnd = CreateWindowA("wine_test_class", "test window", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
+ 100, 200, 300, 400, NULL, NULL, NULL, NULL);
+ flush_events();
+
+ filter = create_vmr9(VMR9Mode_Windowed);
+ flush_events();
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
+ IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
+
+ hr = IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IOverlay_GetWindowHandle(overlay, &hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (winetest_debug > 1) trace("ours %p, theirs %p\n", our_hwnd, hwnd);
+ GetWindowRect(hwnd, &rect);
+
+ tid = GetWindowThreadProcessId(hwnd, NULL);
+ ok(tid == GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid);
+
+ hr = IBaseFilter_QueryInterface(filter, &IID_IVideoWindow, (void **)&window);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ testfilter_init(&source);
+ IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, filter, NULL);
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMemInputPin_GetAllocator(input, &allocator);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
+ hr = IMemAllocator_Commit(allocator);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMemAllocator_Release(allocator);
+ }
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ test_video_window_caption(window, hwnd);
+ test_video_window_style(window, hwnd, our_hwnd);
+ test_video_window_state(window, hwnd, our_hwnd);
+ test_video_window_position(window, hwnd, our_hwnd);
+ test_video_window_autoshow(window, graph, hwnd);
+ test_video_window_owner(window, hwnd, our_hwnd);
+ test_video_window_messages(window, hwnd, our_hwnd);
+
+ hr = IVideoWindow_put_FullScreenMode(window, OATRUE);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_get_FullScreenMode(window, &l);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ monitorinfo.cbSize = sizeof(monitorinfo);
+ GetMonitorInfoW(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitorinfo);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == 1, "Got width %d.\n", width);
+ todo_wine ok(height == 1, "Got height %d.\n", height);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == monitorinfo.rcMonitor.right + 1, "Expected width %d, got %d.\n",
+ monitorinfo.rcMonitor.right + 1, width);
+ todo_wine ok(height == monitorinfo.rcMonitor.bottom + 1, "Expected height %d, got %d.\n",
+ monitorinfo.rcMonitor.bottom + 1, height);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+ IFilterGraph2_Release(graph);
+ IVideoWindow_Release(window);
+ IOverlay_Release(overlay);
+ IMemInputPin_Release(input);
+ IPin_Release(pin);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ DestroyWindow(our_hwnd);
+}
+
START_TEST(vmr9)
{
IBaseFilter *filter;
@@ -1487,6 +2293,7 @@ START_TEST(vmr9)
test_unconnected_filter_state();
test_connect_pin();
test_overlay();
+ test_video_window();
CoUninitialize();
}
--
2.24.0
Dec. 6, 2019
[PATCH v2 2/4] quartz/vmr9: Create the rendering window when the filter is created.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/vmr7.c | 2 +-
dlls/quartz/tests/vmr9.c | 2 +-
dlls/quartz/vmr9.c | 50 +++++++++++++---------------------------
3 files changed, 18 insertions(+), 36 deletions(-)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index b8fd3f53ce..98dfd4551b 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1453,7 +1453,7 @@ static void test_overlay(void)
hwnd = (HWND)0xdeadbeef;
hr = IOverlay_GetWindowHandle(overlay, &hwnd);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
+ ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
IOverlay_Release(overlay);
IPin_Release(pin);
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 1897149575..70b100544c 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1453,7 +1453,7 @@ static void test_overlay(void)
hwnd = (HWND)0xdeadbeef;
hr = IOverlay_GetWindowHandle(overlay, &hwnd);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
+ ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
IOverlay_Release(overlay);
IPin_Release(pin);
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c
index 994e309165..60c19e0019 100644
--- a/dlls/quartz/vmr9.c
+++ b/dlls/quartz/vmr9.c
@@ -294,7 +294,7 @@ static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMedi
info.dwFlags |= VMR9Sample_SyncPoint;
/* If we render ourselves, and this is a preroll sample, discard it */
- if (This->baseControlWindow.baseWindow.hWnd && (info.dwFlags & VMR9Sample_Preroll))
+ if (info.dwFlags & VMR9Sample_Preroll)
{
return S_OK;
}
@@ -374,7 +374,7 @@ static HRESULT VMR9_maybe_init(struct quartz_vmr *This, BOOL force)
HRESULT hr;
TRACE("my mode: %u, my window: %p, my last window: %p\n", This->mode, This->baseControlWindow.baseWindow.hWnd, This->hWndClippingWindow);
- if (This->baseControlWindow.baseWindow.hWnd || !This->renderer.sink.pin.peer)
+ if (This->num_surfaces || !This->renderer.sink.pin.peer)
return S_OK;
if (This->mode == VMR9Mode_Windowless && !This->hWndClippingWindow)
@@ -516,6 +516,7 @@ static void vmr_destroy(struct strmbase_renderer *iface)
CloseHandle(filter->run_event);
FreeLibrary(filter->hD3d9);
+ BaseControlWindow_Destroy(&filter->baseControlWindow);
strmbase_renderer_cleanup(&filter->renderer);
CoTaskMemFree(filter);
}
@@ -1510,13 +1511,10 @@ static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessContr
if (dest)
{
This->target_rect = *dest;
- if (This->baseControlWindow.baseWindow.hWnd)
- {
- FIXME("Output rectangle: %s\n", wine_dbgstr_rect(dest));
- SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
- dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top,
- SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
- }
+ FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest));
+ SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
+ dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW);
}
LeaveCriticalSection(&This->renderer.filter.csFilter);
@@ -1714,12 +1712,10 @@ static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessContr
if (dest)
{
This->target_rect = *dest;
- if (This->baseControlWindow.baseWindow.hWnd)
- {
- FIXME("Output rectangle: %s\n", wine_dbgstr_rect(dest));
- SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
- dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
- }
+ FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest));
+ SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
+ dest->left, dest->top, dest->right - dest->left, dest->bottom - dest->top,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW);
}
LeaveCriticalSection(&This->renderer.filter.csFilter);
@@ -2251,6 +2247,9 @@ static HRESULT vmr_create(IUnknown *outer, void **out, const CLSID *clsid)
if (FAILED(hr))
goto fail;
+ if (FAILED(hr = BaseWindowImpl_PrepareWindow(&pVMR->baseControlWindow.baseWindow)))
+ goto fail;
+
hr = strmbase_video_init(&pVMR->baseControlVideo, &pVMR->renderer.filter,
&pVMR->renderer.sink.pin, &renderer_BaseControlVideoFuncTable);
if (FAILED(hr))
@@ -2265,6 +2264,7 @@ static HRESULT vmr_create(IUnknown *outer, void **out, const CLSID *clsid)
return hr;
fail:
+ BaseWindowImpl_DoneWithWindow(&pVMR->baseControlWindow.baseWindow);
strmbase_renderer_cleanup(&pVMR->renderer);
FreeLibrary(pVMR->hD3d9);
CoTaskMemFree(pVMR);
@@ -2594,9 +2594,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
TRACE("(%p)->()\n", This);
- if (FAILED(BaseWindowImpl_PrepareWindow(&This->pVMR9->baseControlWindow.baseWindow)))
- return FALSE;
-
/* Obtain a monitor and d3d9 device */
d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon);
@@ -2612,7 +2609,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
if (FAILED(hr))
{
ERR("Could not create device: %08x\n", hr);
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
return FALSE;
}
IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
@@ -2634,7 +2630,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
if (FAILED(hr))
{
IVMRSurfaceAllocatorEx9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
return FALSE;
}
@@ -2666,14 +2661,7 @@ static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocato
static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id)
{
- VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
-
- if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
- {
- return S_OK;
- }
-
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
+ TRACE("iface %p, id %#lx.\n", iface, id);
return S_OK;
}
@@ -2688,12 +2676,6 @@ static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPrese
D3DPRESENT_PARAMETERS d3dpp;
HRESULT hr;
- if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
- {
- ERR("No window\n");
- return E_FAIL;
- }
-
if (!This->d3d9_surfaces || !This->reset)
return S_OK;
--
2.24.0
Dec. 6, 2019
[PATCH v2 1/4] strmbase: Correctly implement IVideoWindow::NotifyOwnerMessage().
by Zebediah Figura
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43367
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/videorenderer.c | 40 +++++++++++++++++++++++++++++--
dlls/strmbase/window.c | 24 +++++++++++++++----
2 files changed, 57 insertions(+), 7 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index ec089c8444..b2202d7ae7 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -1812,10 +1812,27 @@ static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hw
ok(state == OATRUE, "Got state %d.\n", state);
}
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
{
+ struct notify_message_params params;
unsigned int i;
OAHWND oahwnd;
+ HANDLE thread;
HRESULT hr;
BOOL ret;
MSG msg;
@@ -1886,14 +1903,33 @@ static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
- todo_wine ok(!ret, "Got unexpected status %#x.\n", ret);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
(WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
- todo_wine ok(!ret, "Got unexpected status %#x.\n", ret);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ ok(!WaitForSingleObject(thread, 1000), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 1000), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
hr = IVideoWindow_put_Owner(window, 0);
ok(hr == S_OK, "Got hr %#x.\n", hr);
diff --git a/dlls/strmbase/window.c b/dlls/strmbase/window.c
index be6646c27a..04132aaab1 100644
--- a/dlls/strmbase/window.c
+++ b/dlls/strmbase/window.c
@@ -654,14 +654,28 @@ HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface, LONG
return S_OK;
}
-HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg, LONG_PTR wParam, LONG_PTR lParam)
+HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface,
+ OAHWND hwnd, LONG message, LONG_PTR wparam, LONG_PTR lparam)
{
- BaseControlWindow* This = impl_from_IVideoWindow(iface);
+ BaseControlWindow *window = impl_from_IVideoWindow(iface);
- TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
+ TRACE("window %p, hwnd %#lx, message %#x, wparam %#lx, lparam %#lx.\n",
+ window, hwnd, message, wparam, lparam);
- if (!PostMessageW(This->baseWindow.hWnd, uMsg, wParam, lParam))
- return E_FAIL;
+ /* That these messages are forwarded, and no others, is stated by the
+ * DirectX documentation, and supported by manual testing. */
+ switch (message)
+ {
+ case WM_ACTIVATEAPP:
+ case WM_DEVMODECHANGE:
+ case WM_DISPLAYCHANGE:
+ case WM_PALETTECHANGED:
+ case WM_PALETTEISCHANGING:
+ case WM_QUERYNEWPALETTE:
+ case WM_SYSCOLORCHANGE:
+ SendMessageW(window->baseWindow.hWnd, message, wparam, lparam);
+ break;
+ }
return S_OK;
}
--
2.24.0
Dec. 6, 2019
Re: [PATCH 4/4] strmbase: Create the video window with the correct styles.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=61442
Your paranoid android.
=== wxppro (32 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== w2003std (32 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== wvistau64 (32 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== w2008s64 (32 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== w7u (32 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== w8 (32 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== w8adm (32 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== w1064v1507 (32 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== wvistau64 (64 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== w2008s64 (64 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
videorenderer.c:1932: Test failed: Got unexpected status 0x80000.
=== wxppro (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== wvistau64 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w2008s64 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w8 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w8adm (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w864 (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1507 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_2scr (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_ar (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_he (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_ja (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_zh_CN (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w2008s64 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1507 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809 (64 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w8 (32 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
=== w8adm (32 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
=== w1064v1507 (32 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
=== w1064v1507 (64 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
Dec. 6, 2019
Re: [PATCH 3/4] quartz/tests: Port IVideoWindow tests to the VMR.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=61441
Your paranoid android.
=== wxppro (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== wvistau64 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w2008s64 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w7u (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w8 (32 bit report) ===
quartz:
vmr7.c:2063: Test failed: Thread should not block.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w8adm (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w864 (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1507 (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809 (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_2scr (32 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_ar (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_he (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_ja (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809_zh_CN (32 bit report) ===
quartz:
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== wvistau64 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w2008s64 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1507 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w1064v1809 (64 bit report) ===
quartz:
vmr7.c:2066: Test failed: Got unexpected status 0x80000.
vmr7.c:2248: Test failed: Got width 1.
vmr7.c:2249: Test failed: Got height 1.
vmr7.c:2252: Test failed: Got width 1025.
vmr7.c:2253: Test failed: Got height 769.
=== w8 (32 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
=== w1064v1507 (32 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
vmr9.c:2066: Test failed: Got unexpected status 0x80000.
Dec. 6, 2019
Re: [PATCH 1/4] strmbase: Correctly implement IVideoWindow::NotifyOwnerMessage().
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=61439
Your paranoid android.
=== wxppro (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w2003std (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== wvistau64 (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w2008s64 (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w7u (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w8 (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w8adm (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809 (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809_2scr (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809_ar (32 bit report) ===
quartz:
videorenderer.c:969: Test failed: Thread should block in Receive().
=== w1064v1809_he (32 bit report) ===
quartz:
videorenderer.c:969: Test failed: Thread should block in Receive().
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809_ja (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1809_zh_CN (32 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== wvistau64 (64 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w2008s64 (64 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w864 (64 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
=== w1064v1507 (64 bit report) ===
quartz:
videorenderer.c:1951: Test failed: Got unexpected status 0x80000.
Dec. 6, 2019
[PATCH 4/4] strmbase: Create the video window with the correct styles.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/videorenderer.c | 8 ++++----
dlls/quartz/tests/vmr7.c | 8 ++++----
dlls/quartz/tests/vmr9.c | 8 ++++----
dlls/strmbase/window.c | 3 ++-
4 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index 320d8920d1..1c64bedbee 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -1467,11 +1467,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1490,10 +1490,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index fa1ae99856..d6d51decec 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1629,11 +1629,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1652,10 +1652,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 3c5986e1f5..c91f9a3527 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1626,11 +1626,11 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
"Got style %#x.\n", style);
hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
@@ -1649,10 +1649,10 @@ static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hw
hr = IVideoWindow_get_WindowStyle(window, &style);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
style = GetWindowLongA(hwnd, GWL_STYLE);
- todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+ ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
diff --git a/dlls/strmbase/window.c b/dlls/strmbase/window.c
index 04132aaab1..07a12eca26 100644
--- a/dlls/strmbase/window.c
+++ b/dlls/strmbase/window.c
@@ -118,7 +118,8 @@ HRESULT WINAPI BaseWindowImpl_PrepareWindow(BaseWindow *This)
return E_FAIL;
}
- This->hWnd = CreateWindowExW(0, class_nameW, windownameW, WS_SIZEBOX,
+ This->hWnd = CreateWindowExW(0, class_nameW, windownameW,
+ WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, NULL);
--
2.24.0
Dec. 6, 2019
[PATCH 3/4] quartz/tests: Port IVideoWindow tests to the VMR.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/vmr7.c | 808 +++++++++++++++++++++++++++++++++++++++
dlls/quartz/tests/vmr9.c | 807 ++++++++++++++++++++++++++++++++++++++
2 files changed, 1615 insertions(+)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index 93c16caede..fa1ae99856 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1565,6 +1565,813 @@ static void test_overlay(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+ int diff = 200;
+ DWORD time;
+ MSG msg;
+
+ time = GetTickCount() + diff;
+ while (diff > 0)
+ {
+ if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
+ break;
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ DispatchMessageA(&msg);
+ diff = time - GetTickCount();
+ }
+}
+
+static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (winetest_debug > 1)
+ trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd, msg, wparam, lparam);
+
+ if (wparam == 0xdeadbeef)
+ return 0;
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+static void test_video_window_caption(IVideoWindow *window, HWND hwnd)
+{
+ WCHAR text[50];
+ BSTR caption;
+ HRESULT hr;
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text));
+
+ caption = SysAllocString(L"foo");
+ hr = IVideoWindow_put_Caption(window, caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ SysFreeString(caption);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"foo"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"foo"), "Got caption %s.\n", wine_dbgstr_w(text));
+}
+
+static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG style;
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_HSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_VSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MAXIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MINIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowStyle(window, style & ~WS_CLIPCHILDREN);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyleEx(window, style | WS_EX_TRANSPARENT);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+}
+
+static BOOL CALLBACK top_window_cb(HWND hwnd, LPARAM ctx)
+{
+ DWORD pid;
+ GetWindowThreadProcessId(hwnd, &pid);
+ if (pid == GetCurrentProcessId() && (GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE))
+ {
+ *(HWND *)ctx = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static HWND get_top_window(void)
+{
+ HWND hwnd;
+ EnumWindows(top_window_cb, (LPARAM)&hwnd);
+ return hwnd;
+}
+
+static void test_video_window_state(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG state;
+ HWND top;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_put_WindowState(window, SW_MINIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MINIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(IsIconic(hwnd), "Window should be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_MAXIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MAXIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should be minimized.\n");
+ ok(IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowState(window, SW_HIDE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_SetWindowForeground(window, TRUE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == our_hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == our_hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+}
+
+static void test_video_window_position(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ LONG left, width, top, height, expect_width, expect_height;
+ RECT rect = {0, 0, 600, 400};
+ HWND top_hwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ AdjustWindowRect(&rect, GetWindowLongA(hwnd, GWL_STYLE), FALSE);
+ expect_width = rect.right - rect.left;
+ expect_height = rect.bottom - rect.top;
+
+ hr = IVideoWindow_put_Left(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_Top(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 0, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Left(window, 10);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Height(window, 200);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 200, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ ok(height == 200, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 200, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_SetWindowPosition(window, 100, 200, 300, 400);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 200, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 300, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 400, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ ok(top == 200, "Got top %d.\n", top);
+ ok(width == 300, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 100, "Got window left %d.\n", rect.left);
+ ok(rect.top == 200, "Got window top %d.\n", rect.top);
+ ok(rect.right == 400, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 600, "Got window bottom %d.\n", rect.bottom);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+}
+
+static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HWND parent, top_hwnd;
+ LONG style, state;
+ OAHWND oahwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == our_hwnd, "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok((style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+
+ ShowWindow(our_hwnd, SW_HIDE);
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == hwnd, "Got top window %p.\n", top_hwnd);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OATRUE, "Got state %d.\n", state);
+}
+
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
+static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ struct notify_message_params params;
+ unsigned int i;
+ OAHWND oahwnd;
+ HANDLE thread;
+ HRESULT hr;
+ BOOL ret;
+ MSG msg;
+
+ static UINT drain_tests[] =
+ {
+ WM_MOUSEACTIVATE,
+ WM_NCLBUTTONDOWN,
+ WM_NCLBUTTONUP,
+ WM_NCLBUTTONDBLCLK,
+ WM_NCRBUTTONDOWN,
+ WM_NCRBUTTONUP,
+ WM_NCRBUTTONDBLCLK,
+ WM_NCMBUTTONDOWN,
+ WM_NCMBUTTONUP,
+ WM_NCMBUTTONDBLCLK,
+ WM_KEYDOWN,
+ WM_KEYUP,
+ WM_MOUSEMOVE,
+ WM_LBUTTONDOWN,
+ WM_LBUTTONUP,
+ WM_LBUTTONDBLCLK,
+ WM_RBUTTONDOWN,
+ WM_RBUTTONUP,
+ WM_RBUTTONDBLCLK,
+ WM_MBUTTONDOWN,
+ WM_MBUTTONUP,
+ WM_MBUTTONDBLCLK,
+ };
+
+ flush_events();
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got window %#lx.\n", oahwnd);
+
+ hr = IVideoWindow_put_MessageDrain(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got window %#lx.\n", oahwnd);
+
+ for (i = 0; i < ARRAY_SIZE(drain_tests); ++i)
+ {
+ SendMessageA(hwnd, drain_tests[i], 0xdeadbeef, 0);
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(ret, "Expected a message.\n");
+ ok(msg.hwnd == our_hwnd, "Got hwnd %p.\n", msg.hwnd);
+ ok(msg.message == drain_tests[i], "Got message %#x.\n", msg.message);
+ ok(msg.wParam == 0xdeadbeef, "Got wparam %#lx.\n", msg.wParam);
+ ok(!msg.lParam, "Got lparam %#lx.\n", msg.lParam);
+ DispatchMessageA(&msg);
+
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(!ret, "Got unexpected message %#x.\n", msg.message);
+ }
+
+ hr = IVideoWindow_put_MessageDrain(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ flush_events();
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SYSCOLORCHANGE, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
+ (WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
+ ok(!WaitForSingleObject(thread, 100), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 100), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+}
+
+static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *graph, HWND hwnd)
+{
+ IMediaControl *control;
+ HRESULT hr;
+ LONG l;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_AutoShow(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OAFALSE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+}
+
+static void test_video_window(void)
+{
+ ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props;
+ VIDEOINFOHEADER vih =
+ {
+ .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+ .bmiHeader.biBitCount = 32,
+ .bmiHeader.biWidth = 600,
+ .bmiHeader.biHeight = 400,
+ .bmiHeader.biPlanes = 1,
+ .bmiHeader.biCompression = BI_RGB,
+ };
+ AM_MEDIA_TYPE req_mt =
+ {
+ .majortype = MEDIATYPE_Video,
+ .subtype = MEDIASUBTYPE_RGB32,
+ .formattype = FORMAT_VideoInfo,
+ .cbFormat = sizeof(vih),
+ .pbFormat = (BYTE *)&vih,
+ };
+ IFilterGraph2 *graph = create_graph();
+ WNDCLASSA window_class = {0};
+ struct testfilter source;
+ IMemAllocator *allocator;
+ IMediaControl *control;
+ LONG width, height, l;
+ IVideoWindow *window;
+ IMemInputPin *input;
+ IBaseFilter *filter;
+ HWND hwnd, our_hwnd;
+ IOverlay *overlay;
+ BSTR caption;
+ HRESULT hr;
+ DWORD tid;
+ ULONG ref;
+ IPin *pin;
+ RECT rect;
+
+ window_class.lpszClassName = "wine_test_class";
+ window_class.lpfnWndProc = window_proc;
+ RegisterClassA(&window_class);
+ our_hwnd = CreateWindowA("wine_test_class", "test window", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
+ 100, 200, 300, 400, NULL, NULL, NULL, NULL);
+ flush_events();
+
+ filter = create_vmr7(0);
+ flush_events();
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
+ IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
+
+ hr = IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IOverlay_GetWindowHandle(overlay, &hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (winetest_debug > 1) trace("ours %p, theirs %p\n", our_hwnd, hwnd);
+ GetWindowRect(hwnd, &rect);
+
+ tid = GetWindowThreadProcessId(hwnd, NULL);
+ ok(tid == GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid);
+
+ hr = IBaseFilter_QueryInterface(filter, &IID_IVideoWindow, (void **)&window);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ testfilter_init(&source);
+ IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, filter, NULL);
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ if (hr == VFW_E_TYPE_NOT_ACCEPTED) /* w7u */
+ {
+ req_mt.subtype = MEDIASUBTYPE_RGB24;
+ vih.bmiHeader.biBitCount = 24;
+ req_props.cbBuffer = 32 * 16 * 3;
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ }
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMemInputPin_GetAllocator(input, &allocator);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
+ hr = IMemAllocator_Commit(allocator);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMemAllocator_Release(allocator);
+ }
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ test_video_window_caption(window, hwnd);
+ test_video_window_style(window, hwnd, our_hwnd);
+ test_video_window_state(window, hwnd, our_hwnd);
+ test_video_window_position(window, hwnd, our_hwnd);
+ test_video_window_autoshow(window, graph, hwnd);
+ test_video_window_owner(window, hwnd, our_hwnd);
+ test_video_window_messages(window, hwnd, our_hwnd);
+
+ hr = IVideoWindow_put_FullScreenMode(window, OATRUE);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_get_FullScreenMode(window, &l);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 600, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 600, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+ IFilterGraph2_Release(graph);
+ IVideoWindow_Release(window);
+ IOverlay_Release(overlay);
+ IMemInputPin_Release(input);
+ IPin_Release(pin);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ DestroyWindow(our_hwnd);
+}
+
START_TEST(vmr7)
{
CoInitialize(NULL);
@@ -1580,6 +2387,7 @@ START_TEST(vmr7)
test_unconnected_filter_state();
test_connect_pin();
test_overlay();
+ test_video_window();
CoUninitialize();
}
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 128d4abbc6..3c5986e1f5 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1562,6 +1562,812 @@ static void test_overlay(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+ int diff = 200;
+ DWORD time;
+ MSG msg;
+
+ time = GetTickCount() + diff;
+ while (diff > 0)
+ {
+ if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
+ break;
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ DispatchMessageA(&msg);
+ diff = time - GetTickCount();
+ }
+}
+
+static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (winetest_debug > 1)
+ trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd, msg, wparam, lparam);
+
+ if (wparam == 0xdeadbeef)
+ return 0;
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+static void test_video_window_caption(IVideoWindow *window, HWND hwnd)
+{
+ WCHAR text[50];
+ BSTR caption;
+ HRESULT hr;
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text));
+
+ caption = SysAllocString(L"foo");
+ hr = IVideoWindow_put_Caption(window, caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ SysFreeString(caption);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!wcscmp(caption, L"foo"), "Got caption %s.\n", wine_dbgstr_w(caption));
+ SysFreeString(caption);
+
+ GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
+ ok(!wcscmp(text, L"foo"), "Got caption %s.\n", wine_dbgstr_w(text));
+}
+
+static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG style;
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
+ "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_HSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_VSCROLL);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MAXIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_WindowStyle(window, style | WS_MINIMIZE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowStyle(window, style & ~WS_CLIPCHILDREN);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ todo_wine ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_WindowStyleEx(window, style | WS_EX_TRANSPARENT);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyleEx(window, &style);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+
+ style = GetWindowLongA(hwnd, GWL_EXSTYLE);
+ ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
+}
+
+static BOOL CALLBACK top_window_cb(HWND hwnd, LPARAM ctx)
+{
+ DWORD pid;
+ GetWindowThreadProcessId(hwnd, &pid);
+ if (pid == GetCurrentProcessId() && (GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE))
+ {
+ *(HWND *)ctx = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static HWND get_top_window(void)
+{
+ HWND hwnd;
+ EnumWindows(top_window_cb, (LPARAM)&hwnd);
+ return hwnd;
+}
+
+static void test_video_window_state(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HRESULT hr;
+ LONG state;
+ HWND top;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_put_WindowState(window, SW_MINIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MINIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(IsIconic(hwnd), "Window should be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_MAXIMIZE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_MAXIMIZE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should be minimized.\n");
+ ok(IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_WindowState(window, SW_HIDE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_SHOW, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OATRUE, "Got state %d.\n", state);
+
+ ok(IsWindowVisible(hwnd), "Window should be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowState(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == SW_HIDE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
+ ok(!IsIconic(hwnd), "Window should not be minimized.\n");
+ ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_SetWindowForeground(window, TRUE);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ ok(GetFocus() == our_hwnd, "Got focus window %p.\n", GetFocus());
+ ok(GetForegroundWindow() == our_hwnd, "Got foreground window %p.\n", GetForegroundWindow());
+ top = get_top_window();
+ ok(top == hwnd, "Got top window %p.\n", top);
+}
+
+static void test_video_window_position(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ LONG left, width, top, height, expect_width, expect_height;
+ RECT rect = {0, 0, 600, 400};
+ HWND top_hwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ AdjustWindowRect(&rect, GetWindowLongA(hwnd, GWL_STYLE), FALSE);
+ expect_width = rect.right - rect.left;
+ expect_height = rect.bottom - rect.top;
+
+ hr = IVideoWindow_put_Left(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_put_Top(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 0, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 0, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Left(window, 10);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ todo_wine ok(height == expect_height, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ todo_wine ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_put_Height(window, 200);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 0, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 200, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 10, "Got left %d.\n", left);
+ ok(top == 0, "Got top %d.\n", top);
+ todo_wine ok(width == expect_width, "Got width %d.\n", width);
+ ok(height == 200, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 10, "Got window left %d.\n", rect.left);
+ ok(rect.top == 0, "Got window top %d.\n", rect.top);
+ todo_wine ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 200, "Got window bottom %d.\n", rect.bottom);
+
+ hr = IVideoWindow_SetWindowPosition(window, 100, 200, 300, 400);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Left(window, &left);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ hr = IVideoWindow_get_Top(window, &top);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(top == 200, "Got top %d.\n", top);
+ hr = IVideoWindow_get_Width(window, &width);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(width == 300, "Got width %d.\n", width);
+ hr = IVideoWindow_get_Height(window, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(height == 400, "Got height %d.\n", height);
+ hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(left == 100, "Got left %d.\n", left);
+ ok(top == 200, "Got top %d.\n", top);
+ ok(width == 300, "Got width %d.\n", width);
+ ok(height == 400, "Got height %d.\n", height);
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == 100, "Got window left %d.\n", rect.left);
+ ok(rect.top == 200, "Got window top %d.\n", rect.top);
+ ok(rect.right == 400, "Got window right %d.\n", rect.right);
+ ok(rect.bottom == 600, "Got window bottom %d.\n", rect.bottom);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+}
+
+static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ HWND parent, top_hwnd;
+ LONG style, state;
+ OAHWND oahwnd;
+ HRESULT hr;
+
+ SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == our_hwnd, "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok((style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
+
+ ShowWindow(our_hwnd, SW_HIDE);
+
+ hr = IVideoWindow_put_Visible(window, OATRUE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OAFALSE, "Got state %d.\n", state);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Owner(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
+
+ parent = GetAncestor(hwnd, GA_PARENT);
+ ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
+ style = GetWindowLongA(hwnd, GWL_STYLE);
+ ok(!(style & WS_CHILD), "Got style %#x.\n", style);
+
+ ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
+ top_hwnd = get_top_window();
+ ok(top_hwnd == hwnd, "Got top window %p.\n", top_hwnd);
+
+ hr = IVideoWindow_get_Visible(window, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(state == OATRUE, "Got state %d.\n", state);
+}
+
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
+static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
+{
+ struct notify_message_params params;
+ unsigned int i;
+ OAHWND oahwnd;
+ HANDLE thread;
+ HRESULT hr;
+ BOOL ret;
+ MSG msg;
+
+ static UINT drain_tests[] =
+ {
+ WM_MOUSEACTIVATE,
+ WM_NCLBUTTONDOWN,
+ WM_NCLBUTTONUP,
+ WM_NCLBUTTONDBLCLK,
+ WM_NCRBUTTONDOWN,
+ WM_NCRBUTTONUP,
+ WM_NCRBUTTONDBLCLK,
+ WM_NCMBUTTONDOWN,
+ WM_NCMBUTTONUP,
+ WM_NCMBUTTONDBLCLK,
+ WM_KEYDOWN,
+ WM_KEYUP,
+ WM_MOUSEMOVE,
+ WM_LBUTTONDOWN,
+ WM_LBUTTONUP,
+ WM_LBUTTONDBLCLK,
+ WM_RBUTTONDOWN,
+ WM_RBUTTONUP,
+ WM_RBUTTONDBLCLK,
+ WM_MBUTTONDOWN,
+ WM_MBUTTONUP,
+ WM_MBUTTONDBLCLK,
+ };
+
+ flush_events();
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!oahwnd, "Got window %#lx.\n", oahwnd);
+
+ hr = IVideoWindow_put_MessageDrain(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(oahwnd == (OAHWND)our_hwnd, "Got window %#lx.\n", oahwnd);
+
+ for (i = 0; i < ARRAY_SIZE(drain_tests); ++i)
+ {
+ SendMessageA(hwnd, drain_tests[i], 0xdeadbeef, 0);
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(ret, "Expected a message.\n");
+ ok(msg.hwnd == our_hwnd, "Got hwnd %p.\n", msg.hwnd);
+ ok(msg.message == drain_tests[i], "Got message %#x.\n", msg.message);
+ ok(msg.wParam == 0xdeadbeef, "Got wparam %#lx.\n", msg.wParam);
+ ok(!msg.lParam, "Got lparam %#lx.\n", msg.lParam);
+ DispatchMessageA(&msg);
+
+ ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
+ ok(!ret, "Got unexpected message %#x.\n", msg.message);
+ }
+
+ hr = IVideoWindow_put_MessageDrain(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ flush_events();
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SYSCOLORCHANGE, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
+ (WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
+ ok(!WaitForSingleObject(thread, 100), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 100), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ hr = IVideoWindow_put_Owner(window, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+}
+
+static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *graph, HWND hwnd)
+{
+ IMediaControl *control;
+ HRESULT hr;
+ LONG l;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(l == OATRUE, "Got %d.\n", l);
+
+ hr = IVideoWindow_put_AutoShow(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_put_Visible(window, OAFALSE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Visible(window, &l);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(l == OAFALSE, "Got %d.\n", l);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+}
+
+static void test_video_window(void)
+{
+ ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props;
+ VIDEOINFOHEADER vih =
+ {
+ .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+ .bmiHeader.biBitCount = 32,
+ .bmiHeader.biWidth = 600,
+ .bmiHeader.biHeight = 400,
+ .bmiHeader.biPlanes = 1,
+ .bmiHeader.biCompression = BI_RGB,
+ };
+ AM_MEDIA_TYPE req_mt =
+ {
+ .majortype = MEDIATYPE_Video,
+ .subtype = MEDIASUBTYPE_RGB32,
+ .formattype = FORMAT_VideoInfo,
+ .cbFormat = sizeof(vih),
+ .pbFormat = (BYTE *)&vih,
+ };
+ IFilterGraph2 *graph = create_graph();
+ WNDCLASSA window_class = {0};
+ struct testfilter source;
+ IMemAllocator *allocator;
+ MONITORINFO monitorinfo;
+ IMediaControl *control;
+ LONG width, height, l;
+ IVideoWindow *window;
+ IMemInputPin *input;
+ IBaseFilter *filter;
+ HWND hwnd, our_hwnd;
+ IOverlay *overlay;
+ BSTR caption;
+ HRESULT hr;
+ DWORD tid;
+ ULONG ref;
+ IPin *pin;
+ RECT rect;
+
+ window_class.lpszClassName = "wine_test_class";
+ window_class.lpfnWndProc = window_proc;
+ RegisterClassA(&window_class);
+ our_hwnd = CreateWindowA("wine_test_class", "test window", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
+ 100, 200, 300, 400, NULL, NULL, NULL, NULL);
+ flush_events();
+
+ filter = create_vmr9(VMR9Mode_Windowed);
+ flush_events();
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
+ IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
+
+ hr = IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IOverlay_GetWindowHandle(overlay, &hwnd);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (winetest_debug > 1) trace("ours %p, theirs %p\n", our_hwnd, hwnd);
+ GetWindowRect(hwnd, &rect);
+
+ tid = GetWindowThreadProcessId(hwnd, NULL);
+ ok(tid == GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid);
+
+ hr = IBaseFilter_QueryInterface(filter, &IID_IVideoWindow, (void **)&window);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_Caption(window, &caption);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_WindowStyle(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_get_AutoShow(window, &l);
+ todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+
+ testfilter_init(&source);
+ IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, filter, NULL);
+ hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMemInputPin_GetAllocator(input, &allocator);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
+ hr = IMemAllocator_Commit(allocator);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMemAllocator_Release(allocator);
+ }
+
+ ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
+
+ test_video_window_caption(window, hwnd);
+ test_video_window_style(window, hwnd, our_hwnd);
+ test_video_window_state(window, hwnd, our_hwnd);
+ test_video_window_position(window, hwnd, our_hwnd);
+ test_video_window_autoshow(window, graph, hwnd);
+ test_video_window_owner(window, hwnd, our_hwnd);
+ test_video_window_messages(window, hwnd, our_hwnd);
+
+ hr = IVideoWindow_put_FullScreenMode(window, OATRUE);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_get_FullScreenMode(window, &l);
+ ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ monitorinfo.cbSize = sizeof(monitorinfo);
+ GetMonitorInfoW(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitorinfo);
+
+ hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == 1, "Got width %d.\n", width);
+ todo_wine ok(height == 1, "Got height %d.\n", height);
+ hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(width == monitorinfo.rcMonitor.right + 1, "Expected width %d, got %d.\n",
+ monitorinfo.rcMonitor.right + 1, width);
+ todo_wine ok(height == monitorinfo.rcMonitor.bottom + 1, "Expected height %d, got %d.\n",
+ monitorinfo.rcMonitor.bottom + 1, height);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+ IFilterGraph2_Release(graph);
+ IVideoWindow_Release(window);
+ IOverlay_Release(overlay);
+ IMemInputPin_Release(input);
+ IPin_Release(pin);
+ ref = IBaseFilter_Release(filter);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ DestroyWindow(our_hwnd);
+}
+
START_TEST(vmr9)
{
IBaseFilter *filter;
@@ -1588,6 +2394,7 @@ START_TEST(vmr9)
test_unconnected_filter_state();
test_connect_pin();
test_overlay();
+ test_video_window();
CoUninitialize();
}
--
2.24.0
Dec. 6, 2019
[PATCH 2/4] quartz/vmr9: Create the rendering window when the filter is created.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/vmr7.c | 2 +-
dlls/quartz/tests/vmr9.c | 2 +-
dlls/quartz/vmr9.c | 50 +++++++++++++---------------------------
3 files changed, 18 insertions(+), 36 deletions(-)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index d8c22bede5..93c16caede 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -1557,7 +1557,7 @@ static void test_overlay(void)
hwnd = (HWND)0xdeadbeef;
hr = IOverlay_GetWindowHandle(overlay, &hwnd);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
+ ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
IOverlay_Release(overlay);
IPin_Release(pin);
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 4acf7cb1d8..128d4abbc6 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -1554,7 +1554,7 @@ static void test_overlay(void)
hwnd = (HWND)0xdeadbeef;
hr = IOverlay_GetWindowHandle(overlay, &hwnd);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
+ ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
IOverlay_Release(overlay);
IPin_Release(pin);
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c
index adf7d6e11a..98e1822593 100644
--- a/dlls/quartz/vmr9.c
+++ b/dlls/quartz/vmr9.c
@@ -294,7 +294,7 @@ static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMedi
info.dwFlags |= VMR9Sample_SyncPoint;
/* If we render ourselves, and this is a preroll sample, discard it */
- if (This->baseControlWindow.baseWindow.hWnd && (info.dwFlags & VMR9Sample_Preroll))
+ if (info.dwFlags & VMR9Sample_Preroll)
{
return S_OK;
}
@@ -374,7 +374,7 @@ static HRESULT VMR9_maybe_init(struct quartz_vmr *This, BOOL force)
HRESULT hr;
TRACE("my mode: %u, my window: %p, my last window: %p\n", This->mode, This->baseControlWindow.baseWindow.hWnd, This->hWndClippingWindow);
- if (This->baseControlWindow.baseWindow.hWnd || !This->renderer.sink.pin.peer)
+ if (This->num_surfaces || !This->renderer.sink.pin.peer)
return S_OK;
if (This->mode == VMR9Mode_Windowless && !This->hWndClippingWindow)
@@ -516,6 +516,7 @@ static void vmr_destroy(struct strmbase_renderer *iface)
CloseHandle(filter->run_event);
FreeLibrary(filter->hD3d9);
+ BaseControlWindow_Destroy(&filter->baseControlWindow);
strmbase_renderer_cleanup(&filter->renderer);
CoTaskMemFree(filter);
}
@@ -1506,13 +1507,10 @@ static HRESULT WINAPI VMR7WindowlessControl_SetVideoPosition(IVMRWindowlessContr
if (dest)
{
This->target_rect = *dest;
- if (This->baseControlWindow.baseWindow.hWnd)
- {
- FIXME("Output rectangle: %s\n", wine_dbgstr_rect(dest));
- SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
- dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top,
- SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
- }
+ FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest));
+ SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
+ dest->left, dest->top, dest->right - dest->left, dest->bottom-dest->top,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW);
}
LeaveCriticalSection(&This->renderer.filter.csFilter);
@@ -1710,12 +1708,10 @@ static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessContr
if (dest)
{
This->target_rect = *dest;
- if (This->baseControlWindow.baseWindow.hWnd)
- {
- FIXME("Output rectangle: %s\n", wine_dbgstr_rect(dest));
- SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left,
- dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW);
- }
+ FIXME("Output rectangle: %s.\n", wine_dbgstr_rect(dest));
+ SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL,
+ dest->left, dest->top, dest->right - dest->left, dest->bottom - dest->top,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW);
}
LeaveCriticalSection(&This->renderer.filter.csFilter);
@@ -2247,6 +2243,9 @@ static HRESULT vmr_create(IUnknown *outer, void **out, const CLSID *clsid)
if (FAILED(hr))
goto fail;
+ if (FAILED(hr = BaseWindowImpl_PrepareWindow(&pVMR->baseControlWindow.baseWindow)))
+ goto fail;
+
hr = strmbase_video_init(&pVMR->baseControlVideo, &pVMR->renderer.filter,
&pVMR->renderer.sink.pin, &renderer_BaseControlVideoFuncTable);
if (FAILED(hr))
@@ -2261,6 +2260,7 @@ static HRESULT vmr_create(IUnknown *outer, void **out, const CLSID *clsid)
return hr;
fail:
+ BaseWindowImpl_DoneWithWindow(&pVMR->baseControlWindow.baseWindow);
strmbase_renderer_cleanup(&pVMR->renderer);
FreeLibrary(pVMR->hD3d9);
CoTaskMemFree(pVMR);
@@ -2590,9 +2590,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
TRACE("(%p)->()\n", This);
- if (FAILED(BaseWindowImpl_PrepareWindow(&This->pVMR9->baseControlWindow.baseWindow)))
- return FALSE;
-
/* Obtain a monitor and d3d9 device */
d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon);
@@ -2608,7 +2605,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
if (FAILED(hr))
{
ERR("Could not create device: %08x\n", hr);
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
return FALSE;
}
IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon);
@@ -2630,7 +2626,6 @@ static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9A
if (FAILED(hr))
{
IVMRSurfaceAllocatorEx9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie);
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
return FALSE;
}
@@ -2662,14 +2657,7 @@ static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocato
static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id)
{
- VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface);
-
- if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
- {
- return S_OK;
- }
-
- BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow);
+ TRACE("iface %p, id %#lx.\n", iface, id);
return S_OK;
}
@@ -2684,12 +2672,6 @@ static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPrese
D3DPRESENT_PARAMETERS d3dpp;
HRESULT hr;
- if (!This->pVMR9->baseControlWindow.baseWindow.hWnd)
- {
- ERR("No window\n");
- return E_FAIL;
- }
-
if (!This->d3d9_surfaces || !This->reset)
return S_OK;
--
2.24.0
Dec. 6, 2019
[PATCH 1/4] strmbase: Correctly implement IVideoWindow::NotifyOwnerMessage().
by Zebediah Figura
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43367
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43765
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/videorenderer.c | 40 +++++++++++++++++++++++++++++--
dlls/strmbase/window.c | 24 +++++++++++++++----
2 files changed, 57 insertions(+), 7 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index a9f938074b..320d8920d1 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -1888,10 +1888,27 @@ static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hw
ok(state == OATRUE, "Got state %d.\n", state);
}
+struct notify_message_params
+{
+ IVideoWindow *window;
+ HWND hwnd;
+ UINT message;
+};
+
+static DWORD CALLBACK notify_message_proc(void *arg)
+{
+ const struct notify_message_params *params = arg;
+ HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ return 0;
+}
+
static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
{
+ struct notify_message_params params;
unsigned int i;
OAHWND oahwnd;
+ HANDLE thread;
HRESULT hr;
BOOL ret;
MSG msg;
@@ -1962,14 +1979,33 @@ static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
- todo_wine ok(!ret, "Got unexpected status %#x.\n", ret);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SETCURSOR,
(WPARAM)hwnd, MAKELONG(HTCLIENT, WM_MOUSEMOVE));
ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
- todo_wine ok(!ret, "Got unexpected status %#x.\n", ret);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
+
+ params.window = window;
+ params.hwnd = our_hwnd;
+ params.message = WM_SYSCOLORCHANGE;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(ret == ((QS_SENDMESSAGE << 16) | QS_SENDMESSAGE), "Got unexpected status %#x.\n", ret);
+
+ PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE);
+ ok(!WaitForSingleObject(thread, 100), "Wait timed out.\n");
+ CloseHandle(thread);
+
+ params.message = WM_SETCURSOR;
+ thread = CreateThread(NULL, 0, notify_message_proc, ¶ms, 0, NULL);
+ ok(!WaitForSingleObject(thread, 100), "Thread should not block.\n");
+ CloseHandle(thread);
+ ret = GetQueueStatus(QS_SENDMESSAGE | QS_POSTMESSAGE);
+ ok(!ret, "Got unexpected status %#x.\n", ret);
hr = IVideoWindow_put_Owner(window, 0);
ok(hr == S_OK, "Got hr %#x.\n", hr);
diff --git a/dlls/strmbase/window.c b/dlls/strmbase/window.c
index be6646c27a..04132aaab1 100644
--- a/dlls/strmbase/window.c
+++ b/dlls/strmbase/window.c
@@ -654,14 +654,28 @@ HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface, LONG
return S_OK;
}
-HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg, LONG_PTR wParam, LONG_PTR lParam)
+HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface,
+ OAHWND hwnd, LONG message, LONG_PTR wparam, LONG_PTR lparam)
{
- BaseControlWindow* This = impl_from_IVideoWindow(iface);
+ BaseControlWindow *window = impl_from_IVideoWindow(iface);
- TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
+ TRACE("window %p, hwnd %#lx, message %#x, wparam %#lx, lparam %#lx.\n",
+ window, hwnd, message, wparam, lparam);
- if (!PostMessageW(This->baseWindow.hWnd, uMsg, wParam, lParam))
- return E_FAIL;
+ /* That these messages are forwarded, and no others, is stated by the
+ * DirectX documentation, and supported by manual testing. */
+ switch (message)
+ {
+ case WM_ACTIVATEAPP:
+ case WM_DEVMODECHANGE:
+ case WM_DISPLAYCHANGE:
+ case WM_PALETTECHANGED:
+ case WM_PALETTEISCHANGING:
+ case WM_QUERYNEWPALETTE:
+ case WM_SYSCOLORCHANGE:
+ SendMessageW(window->baseWindow.hWnd, message, wparam, lparam);
+ break;
+ }
return S_OK;
}
--
2.24.0
Dec. 6, 2019
[PATCH v4] odbccp32: Implement SQLConfigDataSource/W
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/odbccp32/odbccp32.c | 121 +++++++++++++++++++++++++++++--------
dlls/odbccp32/tests/misc.c | 8 +--
2 files changed, 101 insertions(+), 28 deletions(-)
diff --git a/dlls/odbccp32/odbccp32.c b/dlls/odbccp32/odbccp32.c
index a09d6571f3..c842872fa6 100644
--- a/dlls/odbccp32/odbccp32.c
+++ b/dlls/odbccp32/odbccp32.c
@@ -68,6 +68,9 @@ static const WCHAR odbc_error_load_lib_failed[] = {'L','o','a','d',' ','L','i','
static const WCHAR odbc_error_request_failed[] = {'R','e','q','u','e','s','t',' ','F','a','i','l','e','d',0};
static const WCHAR odbc_error_invalid_keyword[] = {'I','n','v','a','l','i','d',' ','k','e','y','w','o','r','d',' ','v','a','l','u','e',0};
+static BOOL (WINAPI *pConfigDSN)(HWND hwnd, WORD request, const char *driver, const char *attr);
+static BOOL (WINAPI *pConfigDSNW)(HWND hwnd, WORD request, const WCHAR *driver, const WCHAR *attr);
+
/* Push an error onto the error stack, taking care of ranges etc. */
static void push_error(int code, LPCWSTR msg)
{
@@ -219,30 +222,6 @@ static BOOL SQLInstall_narrow(int mode, LPSTR buffer, LPCWSTR str, WORD str_leng
return success;
}
-BOOL WINAPI SQLConfigDataSourceW(HWND hwndParent, WORD fRequest,
- LPCWSTR lpszDriver, LPCWSTR lpszAttributes)
-{
- LPCWSTR p;
-
- clear_errors();
- FIXME("%p %d %s %s\n", hwndParent, fRequest, debugstr_w(lpszDriver),
- debugstr_w(lpszAttributes));
-
- for (p = lpszAttributes; *p; p += lstrlenW(p) + 1)
- FIXME("%s\n", debugstr_w(p));
-
- return TRUE;
-}
-
-BOOL WINAPI SQLConfigDataSource(HWND hwndParent, WORD fRequest,
- LPCSTR lpszDriver, LPCSTR lpszAttributes)
-{
- FIXME("%p %d %s %s\n", hwndParent, fRequest, debugstr_a(lpszDriver),
- debugstr_a(lpszAttributes));
- clear_errors();
- return TRUE;
-}
-
static HMODULE load_config_driver(const WCHAR *driver)
{
static WCHAR reg_driver[] = {'d','r','i','v','e','r',0};
@@ -359,6 +338,100 @@ fail:
return FALSE;
}
+BOOL WINAPI SQLConfigDataSourceW(HWND hwnd, WORD request, LPCWSTR driver, LPCWSTR attributes)
+{
+ HMODULE mod;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %s, %s\n", hwnd, request, debugstr_w(driver), debugstr_w(attributes));
+ if (TRACE_ON(odbc))
+ {
+ const WCHAR *p;
+ for (p = attributes; *p; p += lstrlenW(p) + 1)
+ TRACE("%s\n", debugstr_w(p));
+ }
+
+ clear_errors();
+
+ mod = load_config_driver(driver);
+ if (!mod)
+ return FALSE;
+
+ pConfigDSNW = (void*)GetProcAddress(mod, "ConfigDSNW");
+ if(pConfigDSNW)
+ ret = pConfigDSNW(hwnd, request, driver, attributes);
+ else
+ ERR("Failed to find ConfigDSNW\n");
+
+ if (!ret)
+ push_error(ODBC_ERROR_REQUEST_FAILED, odbc_error_request_failed);
+
+ FreeLibrary(mod);
+
+ return ret;
+}
+
+BOOL WINAPI SQLConfigDataSource(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attributes)
+{
+ HMODULE mod;
+ BOOL ret = FALSE;
+ WCHAR *driverW;
+
+ TRACE("%p, %d, %s, %s\n", hwnd, request, debugstr_a(driver), debugstr_a(attributes));
+
+ if (TRACE_ON(odbc))
+ {
+ const char *p;
+ for (p = attributes; *p; p += lstrlenA(p) + 1)
+ TRACE("%s\n", debugstr_a(p));
+ }
+
+ clear_errors();
+
+ driverW = heap_strdupAtoW(driver);
+ if (!driverW)
+ {
+ push_error(ODBC_ERROR_OUT_OF_MEM, odbc_error_out_of_mem);
+ return FALSE;
+ }
+
+ mod = load_config_driver(driverW);
+ if (!mod)
+ {
+ heap_free(driverW);
+ return FALSE;
+ }
+
+ pConfigDSN = (void*)GetProcAddress(mod, "ConfigDSN");
+ if (pConfigDSN)
+ {
+ TRACE("Calling ConfigDSN\n");
+ ret = pConfigDSN(hwnd, request, driver, attributes);
+ }
+ else
+ {
+ pConfigDSNW = (void*)GetProcAddress(mod, "ConfigDSNW");
+ if (pConfigDSNW)
+ {
+ WCHAR *attr = NULL;
+ TRACE("Calling ConfigDSNW\n");
+
+ attr = SQLInstall_strdup_multi(attributes);
+ if(attr)
+ ret = pConfigDSNW(hwnd, request, driverW, attr);
+ heap_free(attr);
+ }
+ }
+
+ if (!ret)
+ push_error(ODBC_ERROR_REQUEST_FAILED, odbc_error_request_failed);
+
+ heap_free(driverW);
+ FreeLibrary(mod);
+
+ return ret;
+}
+
BOOL WINAPI SQLConfigDriverW(HWND hwnd, WORD request, LPCWSTR driver,
LPCWSTR args, LPWSTR msg, WORD msgmax, WORD *msgout)
{
diff --git a/dlls/odbccp32/tests/misc.c b/dlls/odbccp32/tests/misc.c
index e2f48ee732..0120504227 100644
--- a/dlls/odbccp32/tests/misc.c
+++ b/dlls/odbccp32/tests/misc.c
@@ -751,10 +751,10 @@ static void test_SQLConfigDataSource(void)
BOOL ret;
ret = SQLConfigDataSource(0, ODBC_ADD_DSN, "SQL Server", "DSN=WINEMQIS\0Database=MQIS\0\0");
- ok(ret, "got %d\n", ret);
+ todo_wine ok(ret, "got %d\n", ret);
ret = SQLConfigDataSource(0, ODBC_REMOVE_DSN, "SQL Server", "DSN=WINEMQIS\0\0");
- ok(ret, "got %d\n", ret);
+ todo_wine ok(ret, "got %d\n", ret);
ret = SQLConfigDataSource(0, ODBC_REMOVE_DSN, "SQL Server", "DSN=WINEMQIS\0\0");
if(!ret)
@@ -767,8 +767,8 @@ static void test_SQLConfigDataSource(void)
}
ret = SQLConfigDataSource(0, ODBC_ADD_DSN, "ODBC driver", "DSN=ODBC data source\0\0");
- todo_wine ok(!ret, "got %d\n", ret);
- todo_wine check_error(ODBC_ERROR_COMPONENT_NOT_FOUND);
+ ok(!ret, "got %d\n", ret);
+ check_error(ODBC_ERROR_COMPONENT_NOT_FOUND);
}
START_TEST(misc)
--
2.17.1
Dec. 5, 2019
[PATCH v3 3/3] xmllite: Expand test for any unparsed data at end of XML.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 3 ++-
dlls/xmllite/tests/reader.c | 2 --
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 79e5c2253a..c4b0fe521d 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -2562,6 +2562,7 @@ static HRESULT reader_parse_content(xmlreader *reader)
static HRESULT reader_parse_nextnode(xmlreader *reader)
{
+ const encoded_buffer *buffer = &reader->input->buffer->utf16;
XmlNodeType nodetype = reader_get_nodetype(reader);
HRESULT hr;
@@ -2662,7 +2663,7 @@ static HRESULT reader_parse_nextnode(xmlreader *reader)
hr = reader_parse_misc(reader);
if (hr != S_FALSE) return hr;
- if (*reader_get_ptr(reader))
+ if (buffer->cur*sizeof(WCHAR) < buffer->written)
{
WARN("found garbage in the end of XML\n");
return WC_E_SYNTAX;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index b02301907d..7ad548d081 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1051,7 +1051,6 @@ static void test_read_nul(void)
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
@@ -1077,7 +1076,6 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
--
2.23.0
Dec. 5, 2019
[PATCH v3 2/3] xmllite: Whitespace node not returned when followed by invalid character.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 12 ++++++++++--
dlls/xmllite/tests/reader.c | 2 --
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index eddc4d8eec..79e5c2253a 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -1113,8 +1113,8 @@ static inline UINT reader_get_cur(xmlreader *reader)
static inline WCHAR *reader_get_ptr(xmlreader *reader)
{
encoded_buffer *buffer = &reader->input->buffer->utf16;
- WCHAR *ptr = (WCHAR*)buffer->data + buffer->cur;
- if (!*ptr) reader_more(reader);
+ if (buffer->cur*sizeof(WCHAR) >= buffer->written)
+ reader_more(reader);
return (WCHAR*)buffer->data + buffer->cur;
}
@@ -1714,8 +1714,16 @@ static HRESULT reader_parse_whitespace(xmlreader *reader)
{
strval value;
UINT start;
+ const encoded_buffer *buffer = &reader->input->buffer->utf16;
reader_skipspaces(reader);
+
+ /* Do NOT return Whitespace node if followed by a character other than '<'.
+ * The reader_skipspaces call should have already read in the character. */
+ if (buffer->cur*sizeof(WCHAR) < buffer->written &&
+ *reader_get_ptr2(reader, buffer->cur) != '<')
+ return WC_E_SYNTAX;
+
if (is_reader_pending(reader)) return S_OK;
start = reader->resume[XmlReadResume_Body];
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 88b9103e1e..b02301907d 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1064,10 +1064,8 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine {
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
-}
stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
--
2.23.0
Dec. 5, 2019
[PATCH v3 1/3] xmllite/tests: Extract nul-character test from XML declaration test.
by Jeff Smith
The comments in the XML declaration test suggest that it is supposed to
be to checking for failure when no element follows the XML declaration.
However, the error being tested for is due to a nul character in the
input stream.
Create a separate test for nul-character errors, and fix the XML
declaration test accordingly.
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/tests/reader.c | 83 +++++++++++++++++++++++++++++--------
1 file changed, 66 insertions(+), 17 deletions(-)
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 41adad1598..88b9103e1e 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -863,7 +863,6 @@ static void test_read_xmldeclaration(void)
{ {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
};
IXmlReader *reader;
- IStream *stream;
HRESULT hr;
XmlNodeType type;
UINT count = 0, len, i;
@@ -873,10 +872,7 @@ static void test_read_xmldeclaration(void)
hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
-
- hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
- ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_full);
hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "got %08x\n", hr);
@@ -968,19 +964,19 @@ static void test_read_xmldeclaration(void)
type = XmlNodeType_XmlDeclaration;
hr = IXmlReader_Read(reader, &type);
- /* newer versions return syntax error here cause document is incomplete,
- it makes more sense than invalid char error */
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(type == XmlNodeType_Whitespace, "expected XmlNodeType_Whitespace, got %s\n", type_to_str(type));
+
+ type = XmlNodeType_Whitespace;
+ hr = IXmlReader_Read(reader, &type);
todo_wine {
- ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
+ ok(hr == WC_E_ROOTELEMENT, "got %08x\n", hr);
ok(type == XmlNodeType_None, "got %d\n", type);
+ TEST_READER_STATE(reader, XmlReadState_Error);
}
- IStream_Release(stream);
/* test short variant */
- stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
-
- hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
- ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_short);
read_node(reader, XmlNodeType_XmlDeclaration);
TEST_READER_POSITION2(reader, 1, 3, ~0u, 21);
@@ -1027,14 +1023,66 @@ todo_wine {
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
- ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
+ ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
- TEST_READER_POSITION(reader, 1, 41);
+
+ IXmlReader_Release(reader);
+}
+
+static void test_read_nul(void)
+{
+ static const char xml_empty[] = "<a/>";
+ static const char xml_ws[] = "<a/> ";
+ static const char xml_comment[] = "<a/><!-- comment -->";
+ IXmlReader *reader;
+ XmlNodeType type;
+ IStream *stream;
+ HRESULT hr;
+
+ hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
+ ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+
+ stream = create_stream_on_data(xml_empty, sizeof(xml_empty));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
todo_wine
- TEST_READER_STATE(reader, XmlReadState_Error);
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+ stream = create_stream_on_data(xml_ws, sizeof(xml_ws));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine {
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+}
+
+ stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+ read_node(reader, XmlNodeType_Comment);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+
IXmlReader_Release(reader);
}
@@ -2672,6 +2720,7 @@ START_TEST(reader)
test_read_pending();
test_readvaluechunk();
test_read_xmldeclaration();
+ test_read_nul();
test_reader_properties();
test_prefix();
test_namespaceuri();
--
2.23.0
Dec. 5, 2019
[PATCH v2 3/3] xmllite: Expand test for any unparsed data at end of XML.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 3 ++-
dlls/xmllite/tests/reader.c | 2 --
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 79e5c2253a..c4b0fe521d 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -2562,6 +2562,7 @@ static HRESULT reader_parse_content(xmlreader *reader)
static HRESULT reader_parse_nextnode(xmlreader *reader)
{
+ const encoded_buffer *buffer = &reader->input->buffer->utf16;
XmlNodeType nodetype = reader_get_nodetype(reader);
HRESULT hr;
@@ -2662,7 +2663,7 @@ static HRESULT reader_parse_nextnode(xmlreader *reader)
hr = reader_parse_misc(reader);
if (hr != S_FALSE) return hr;
- if (*reader_get_ptr(reader))
+ if (buffer->cur*sizeof(WCHAR) < buffer->written)
{
WARN("found garbage in the end of XML\n");
return WC_E_SYNTAX;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 72f9ca902d..878c14f7ef 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1051,7 +1051,6 @@ static void test_read_nul(void)
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
@@ -1077,7 +1076,6 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
--
2.23.0
Dec. 5, 2019
[PATCH v2 2/3] xmllite: Whitespace node not returned when followed by invalid character.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 12 ++++++++++--
dlls/xmllite/tests/reader.c | 2 --
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index eddc4d8eec..79e5c2253a 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -1113,8 +1113,8 @@ static inline UINT reader_get_cur(xmlreader *reader)
static inline WCHAR *reader_get_ptr(xmlreader *reader)
{
encoded_buffer *buffer = &reader->input->buffer->utf16;
- WCHAR *ptr = (WCHAR*)buffer->data + buffer->cur;
- if (!*ptr) reader_more(reader);
+ if (buffer->cur*sizeof(WCHAR) >= buffer->written)
+ reader_more(reader);
return (WCHAR*)buffer->data + buffer->cur;
}
@@ -1714,8 +1714,16 @@ static HRESULT reader_parse_whitespace(xmlreader *reader)
{
strval value;
UINT start;
+ const encoded_buffer *buffer = &reader->input->buffer->utf16;
reader_skipspaces(reader);
+
+ /* Do NOT return Whitespace node if followed by a character other than '<'.
+ * The reader_skipspaces call should have already read in the character. */
+ if (buffer->cur*sizeof(WCHAR) < buffer->written &&
+ *reader_get_ptr2(reader, buffer->cur) != '<')
+ return WC_E_SYNTAX;
+
if (is_reader_pending(reader)) return S_OK;
start = reader->resume[XmlReadResume_Body];
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 40d39c22f5..72f9ca902d 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1064,10 +1064,8 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine {
ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
-}
stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
--
2.23.0
Dec. 5, 2019
[PATCH v2 1/3] xmllite/tests: Extract nul-character test from XML declaration test.
by Jeff Smith
The comments in the XML declaration test suggest that it is supposed to
be to checking for failure when no element follows the XML declaration.
However, the error being tested for is due to a nul character in the
input stream.
Create a separate test for nul-character errors, and fix the XML
declaration test accordingly.
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/tests/reader.c | 83 +++++++++++++++++++++++++++++--------
1 file changed, 66 insertions(+), 17 deletions(-)
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 41adad1598..40d39c22f5 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -863,7 +863,6 @@ static void test_read_xmldeclaration(void)
{ {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
};
IXmlReader *reader;
- IStream *stream;
HRESULT hr;
XmlNodeType type;
UINT count = 0, len, i;
@@ -873,10 +872,7 @@ static void test_read_xmldeclaration(void)
hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
-
- hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
- ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_full);
hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "got %08x\n", hr);
@@ -968,19 +964,19 @@ static void test_read_xmldeclaration(void)
type = XmlNodeType_XmlDeclaration;
hr = IXmlReader_Read(reader, &type);
- /* newer versions return syntax error here cause document is incomplete,
- it makes more sense than invalid char error */
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(type == XmlNodeType_Whitespace, "expected XmlNodeType_Whitespace, got %s\n", type_to_str(type));
+
+ type = XmlNodeType_Whitespace;
+ hr = IXmlReader_Read(reader, &type);
todo_wine {
- ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
+ ok(hr == WC_E_ROOTELEMENT, "got %08x\n", hr);
ok(type == XmlNodeType_None, "got %d\n", type);
+ TEST_READER_STATE(reader, XmlReadState_Error);
}
- IStream_Release(stream);
/* test short variant */
- stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
-
- hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
- ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_short);
read_node(reader, XmlNodeType_XmlDeclaration);
TEST_READER_POSITION2(reader, 1, 3, ~0u, 21);
@@ -1027,14 +1023,66 @@ todo_wine {
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
- ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
+ ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
- TEST_READER_POSITION(reader, 1, 41);
+
+ IXmlReader_Release(reader);
+}
+
+static void test_read_nul(void)
+{
+ static const char xml_empty[] = "<a/>";
+ static const char xml_ws[] = "<a/> ";
+ static const char xml_comment[] = "<a/><!-- comment -->";
+ IXmlReader *reader;
+ XmlNodeType type;
+ IStream *stream;
+ HRESULT hr;
+
+ hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
+ ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+
+ stream = create_stream_on_data(xml_empty, sizeof(xml_empty));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
todo_wine
- TEST_READER_STATE(reader, XmlReadState_Error);
+ ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+ stream = create_stream_on_data(xml_ws, sizeof(xml_ws));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine {
+ ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+}
+
+ stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+ read_node(reader, XmlNodeType_Comment);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine
+ ok(hr == WC_E_SYNTAX, "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+
IXmlReader_Release(reader);
}
@@ -2672,6 +2720,7 @@ START_TEST(reader)
test_read_pending();
test_readvaluechunk();
test_read_xmldeclaration();
+ test_read_nul();
test_reader_properties();
test_prefix();
test_namespaceuri();
--
2.23.0
Dec. 5, 2019
[PATCH] kernel32: Set all %eax bits on Wow64EnableWow64FsRedirection return.
by Piotr Caban
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47565
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
---
The Wow64EnableWow64FsRedirection function, when compiled with gcc
9.2.0, uses setz %al to set return value. Microsoft C++ Redistributable
installers are depending on all %eax bits being set.
dlls/kernel32/kernel32.spec | 2 +-
dlls/kernel32/path.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
Dec. 5, 2019
[PATCH v2] msxml3: all string passed to IXMLDOMDocument_load() need to be URL-unescaped
by Damjan Jovanovic
msxml3 allows URL escape sequences even for C:\ style paths.
eg. C:\Program%20Files\...
Try 2 determines URL length dynamically, suppresses some compiler
const warnings, and cleans up tests.
Signed-off-by: Damjan Jovanovic <damjan.jov(a)gmail.com>
---
dlls/msxml3/bsc.c | 33 ++++++++++++++++++++++++++++-----
dlls/msxml3/tests/domdoc.c | 17 +++++++++++++++++
2 files changed, 45 insertions(+), 5 deletions(-)
Dec. 5, 2019
[PATCH v3 1/3] bcrypt: Add support for signing hashes with ECDSA keys.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v3: Fix accidental return of 0 (STATUS_SUCCESS) when gnutls_decode_rs_value fails.
---
dlls/bcrypt/gnutls.c | 147 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 130 insertions(+), 17 deletions(-)
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index a6a07fff19..6e0bfef97b 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -92,6 +92,7 @@ MAKE_FUNCPTR(gnutls_cipher_decrypt2);
MAKE_FUNCPTR(gnutls_cipher_deinit);
MAKE_FUNCPTR(gnutls_cipher_encrypt2);
MAKE_FUNCPTR(gnutls_cipher_init);
+MAKE_FUNCPTR(gnutls_decode_rs_value);
MAKE_FUNCPTR(gnutls_global_deinit);
MAKE_FUNCPTR(gnutls_global_init);
MAKE_FUNCPTR(gnutls_global_set_log_function);
@@ -189,6 +190,7 @@ BOOL gnutls_initialize(void)
LOAD_FUNCPTR(gnutls_cipher_deinit)
LOAD_FUNCPTR(gnutls_cipher_encrypt2)
LOAD_FUNCPTR(gnutls_cipher_init)
+ LOAD_FUNCPTR(gnutls_decode_rs_value)
LOAD_FUNCPTR(gnutls_global_deinit)
LOAD_FUNCPTR(gnutls_global_init)
LOAD_FUNCPTR(gnutls_global_set_log_function)
@@ -711,6 +713,7 @@ NTSTATUS key_asymmetric_generate( struct key *key )
break;
case ALG_ID_ECDH_P256:
+ case ALG_ID_ECDSA_P256:
pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */
bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1 );
break;
@@ -1029,6 +1032,17 @@ static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULO
}
}
+static gnutls_digest_algorithm_t get_digest_from_id( const WCHAR *alg_id )
+{
+ if (!strcmpW( alg_id, BCRYPT_SHA1_ALGORITHM )) return GNUTLS_DIG_SHA1;
+ if (!strcmpW( alg_id, BCRYPT_SHA256_ALGORITHM )) return GNUTLS_DIG_SHA256;
+ if (!strcmpW( alg_id, BCRYPT_SHA384_ALGORITHM )) return GNUTLS_DIG_SHA384;
+ if (!strcmpW( alg_id, BCRYPT_SHA512_ALGORITHM )) return GNUTLS_DIG_SHA512;
+ if (!strcmpW( alg_id, BCRYPT_MD2_ALGORITHM )) return GNUTLS_DIG_MD2;
+ if (!strcmpW( alg_id, BCRYPT_MD5_ALGORITHM )) return GNUTLS_DIG_MD5;
+ return -1;
+}
+
NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len, UCHAR *signature,
ULONG signature_len, DWORD flags )
{
@@ -1068,11 +1082,7 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
if (!(flags & BCRYPT_PAD_PKCS1) || !info) return STATUS_INVALID_PARAMETER;
if (!info->pszAlgId) return STATUS_INVALID_SIGNATURE;
- if (!strcmpW( info->pszAlgId, BCRYPT_SHA1_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA1;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA256_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA256;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA384_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA384;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA512_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA512;
- else
+ if ((hash_alg = get_digest_from_id(info->pszAlgId)) == -1)
{
FIXME( "hash algorithm %s not supported\n", debugstr_w(info->pszAlgId) );
return STATUS_NOT_SUPPORTED;
@@ -1107,26 +1117,130 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
return (ret < 0) ? STATUS_INVALID_SIGNATURE : STATUS_SUCCESS;
}
+static unsigned int get_signature_length( enum alg_id id )
+{
+ switch (id)
+ {
+ case ALG_ID_ECDSA_P256: return 64;
+ case ALG_ID_ECDSA_P384: return 96;
+ default:
+ FIXME( "unhandled algorithm %u\n", id );
+ return 0;
+ }
+}
+
+NTSTATUS format_gnutls_signature( enum alg_id type, gnutls_datum_t signature, UCHAR *output,
+ ULONG output_len, ULONG *ret_len )
+{
+ switch (type)
+ {
+ case ALG_ID_RSA:
+ case ALG_ID_RSA_SIGN:
+ {
+ if (output_len < signature.size) return STATUS_BUFFER_TOO_SMALL;
+ memcpy( output, signature.data, signature.size );
+ *ret_len = signature.size;
+ return STATUS_SUCCESS;
+ }
+ case ALG_ID_ECDSA_P256:
+ case ALG_ID_ECDSA_P384:
+ {
+ int err;
+ unsigned int pad_size, sig_len = get_signature_length( type );
+ gnutls_datum_t r, s; /* format as r||s */
+
+ if ((err = pgnutls_decode_rs_value( &signature, &r, &s )))
+ {
+ ERR( "failed to get R/S values from signature %u\n", err );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ if (output_len < sig_len) return STATUS_BUFFER_TOO_SMALL;
+
+ /* remove prepended zero byte */
+ if (r.size % 2)
+ {
+ r.size--;
+ r.data += 1;
+ }
+ if (s.size % 2)
+ {
+ s.size--;
+ s.data += 1;
+ }
+
+ if (r.size != s.size || r.size + s.size > sig_len)
+ {
+ ERR( "we didn't get a correct signature\n" );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ pad_size = (sig_len / 2) - s.size;
+ memset( output, 0, sig_len );
+
+ memcpy( output + pad_size, r.data, r.size );
+ memcpy( output + (sig_len / 2) + pad_size, s.data, s.size );
+
+ *ret_len = sig_len;
+ return STATUS_SUCCESS;
+ }
+ default:
+ return STATUS_INTERNAL_ERROR;
+ }
+}
+
NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output,
ULONG output_len, ULONG *ret_len, ULONG flags )
{
BCRYPT_PKCS1_PADDING_INFO *pad = padding;
gnutls_datum_t hash, signature;
+ gnutls_digest_algorithm_t hash_alg;
+ NTSTATUS status;
int ret;
- if (key->alg_id != ALG_ID_RSA && key->alg_id != ALG_ID_RSA_SIGN)
+ if (key->alg_id == ALG_ID_ECDSA_P256 || key->alg_id == ALG_ID_ECDSA_P384)
{
- FIXME( "algorithm %u not supported\n", key->alg_id );
- return STATUS_NOT_IMPLEMENTED;
+ /* With ECDSA, we find the digest algorithm from the hash length, and verify it */
+ switch (input_len)
+ {
+ case 20: hash_alg = GNUTLS_DIG_SHA1; break;
+ case 32: hash_alg = GNUTLS_DIG_SHA256; break;
+ case 48: hash_alg = GNUTLS_DIG_SHA384; break;
+ case 64: hash_alg = GNUTLS_DIG_SHA512; break;
+
+ default:
+ FIXME( "hash size %u not yet supported\n", input_len );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (flags == BCRYPT_PAD_PKCS1 && pad && pad->pszAlgId && get_digest_from_id( pad->pszAlgId ) != hash_alg)
+ {
+ WARN( "incorrect hashing algorithm %s, expected %u\n", debugstr_w(pad->pszAlgId), hash_alg );
+ return STATUS_INVALID_PARAMETER;
+ }
}
- if (flags != BCRYPT_PAD_PKCS1)
+ else if (flags == BCRYPT_PAD_PKCS1)
{
- FIXME( "flags %08x not implemented\n", flags );
- return STATUS_NOT_IMPLEMENTED;
+ if (!pad || !pad->pszAlgId)
+ {
+ WARN( "padding info not found\n" );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hash_alg = get_digest_from_id( pad->pszAlgId )) == -1)
+ {
+ FIXME( "hash algorithm %s not recognized\n", debugstr_w(pad->pszAlgId) );
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+ else if (!flags)
+ {
+ WARN( "invalid flags %08x\n", flags );
+ return STATUS_INVALID_PARAMETER;
}
- if (!pad || !pad->pszAlgId || lstrcmpiW(pad->pszAlgId, BCRYPT_SHA1_ALGORITHM))
+ else
{
- FIXME( "%s padding not implemented\n", debugstr_w(pad ? pad->pszAlgId : NULL) );
+ FIXME( "flags %08x not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED;
}
@@ -1143,17 +1257,16 @@ NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULON
signature.data = NULL;
signature.size = 0;
- if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, GNUTLS_DIG_SHA1, 0, &hash, &signature )))
+ if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, hash_alg, 0, &hash, &signature )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- if (output_len >= signature.size) memcpy( output, signature.data, signature.size );
- *ret_len = signature.size;
+ status = format_gnutls_signature( key->alg_id, signature, output, output_len, ret_len );
free( signature.data );
- return STATUS_SUCCESS;
+ return status;
}
NTSTATUS key_destroy( struct key *key )
--
2.24.0
Dec. 5, 2019
Re: [PATCH 1/3] bcrypt: Add support for signing hashes with ECDSA keys.
by Derek Lesho
On 12/5/19 4:55 AM, Hans Leidekker wrote:
> + if ((err = pgnutls_decode_rs_value( &signature, &r, &s )))
> + {
> + ERR( "failed to get R/S values from signature %u\n", err );
> + return 0;
> + }
As I was looking at this patch again making a version that will work in
Proton, I noticed this mistake I made. I'll send a correction soon.
Dec. 5, 2019
Re: [PATCH] msxml3: all string passed to IXMLDOMDocument_load() need to be URL-unescaped
by Damjan Jovanovic
On Thu, Dec 5, 2019 at 1:45 PM Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
> Do we need to unescape if it's not a file:// url? I was hoping we could
> find some IUri/path API flags to do what we need for us.
>
>
The CreateUri() function called at the end of create_uri() does its own
unescaping, which is why I didn't pass it the unescaped URL, but left it
with the original URL. My unescaping is done for the benefit of the earlier
function, PathIsURLW(), which doesn't unescape internally, and for
PathSearchAndQualifyW() and UrlCreateFromPathW(), which require paths not
URLs, and paths are always unescaped.
> Another concern is path/url max lengths are used seemingly randomly, and
> it's not a problem with your change, but with existing code. I think
> asking for required length and allocating it is better.
>
>
Sure.
> + /* Regular local path with some URL encoded characters. */
> + strcpy(path2, path);
> + n = strlen(path2);
> + path2[n-1] = '%';
> + path2[n] = '6';
> + path2[n+1] = 'C';
> + path2[n+2] = '\0'; /* C:\path\to\winetest.xm%6C */
> + test_doc_load_from_path(doc, path2);
>
> Could you make this more readable? Maybe strcat-ing escaped file name as
> string literal instead.
>
Will do.
>
> + /* Regular local path with all URL encoded characters. */
> + percent_path = HeapAlloc(GetProcessHeap(), 0, 3*n + 1);
> + for (i = 0; i < n; i++)
> + {
> + static char hex_tab[] = "0123456789ABCDEF";
> + percent_path[3*i] = '%';
> + percent_path[3*i + 1] = hex_tab[path[i] >> 4];
> + percent_path[3*i + 2] = hex_tab[path[i] & 0xF];
> + }
> + percent_path[3*n] = '\0';
> + test_doc_load_from_path(doc, percent_path);
> + HeapFree(GetProcessHeap(), 0, percent_path);
>
> Couple of cases would be enough, like you did earlier for "l" -> %6c, and
> another one for " " -> %20. Space is actually not tested by this patch, and
> that's what application is using. If you still want to encode it entirely,
> please add a helper function.
>
Agreed. It would actually be good to test with both a space and %20.
Dec. 5, 2019
[PATCH] mscoree: Ignore empty privatePath.
by Vincent Povirk
Signed-off-by: Vincent Povirk <vincent(a)codeweavers.com>
---
Spotted by Rafał Mużyło.
dlls/mscoree/corruntimehost.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c
index e932a7f58be..a900ed6a3e2 100644
--- a/dlls/mscoree/corruntimehost.c
+++ b/dlls/mscoree/corruntimehost.c
@@ -1478,7 +1478,7 @@ __int32 WINAPI _CorExeMain(void)
wcscat(config_file, dotconfig);
hr = parse_config_file(config_file, &parsed_config);
- if (SUCCEEDED(hr) && parsed_config.private_path)
+ if (SUCCEEDED(hr) && parsed_config.private_path && parsed_config.private_path[0])
{
for(i = 0; parsed_config.private_path[i] != 0; i++)
if (parsed_config.private_path[i] == ';') number_of_private_paths++;
--
2.17.1
Dec. 5, 2019
Re: mscoree: fix an error in string access
by Vincent Povirk (they/them)
Thanks. Unfortunately, this doesn't seem to have been picked up by the
patch tracker.
I think we should treat an empty string the same as a NULL string and
not try to parse it at all.
Dec. 5, 2019
Re: [wine-devel] Wine staging 4.21 release
by Zebediah Figura
On 12/5/19 9:57 AM, Zebediah Figura wrote:
> On 12/4/19 4:56 PM, Alan W. Irwin wrote:
>> On 2019-11-30 04:56-0000 Alistair Leslie-Hughes wrote:
>>
>>> Binary packages for various distributions will be available from:
>>> https://www.winehq.org/download
>>>
>>> Summary since last release
>>> * Rebased to current wine 4.21 (833 patches are applied to wine vanilla)
>>>
>>> Upstreamed (Either directly from staging or fixed with a similar patch).
>>> * none
>>>
>>> Added:
>>> * [47668] kernelbase: Improve stub for ReOpenFile and add small test
>>> * [48138] League of Legends 9.23: Crash after champ select
>>> * [47970] Legends of Runeterra crashes at launch
>>> * [40334] AION - Wine /Unhandled exception: page fault on read access to
>>> 0x00000000 in 64-bit code (0x0000000000000000).
>>> * [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high
>>> memory pointers allocated
>>> * [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist
>>> package fails to load (Wine doesn't respect 44-bit user-mode VA
>>> limitation from Windows < 8.1)
>>>
>>> Updated:
>>> * d3d9-Direct3DShaderValidatorCreate9
>>> * winecfg-Staging
>>
>> [...]
>>
>> Hi Alistair:
>>
>> Could you explain how these patch numbers in your report are related with each other?
>> For example, my initial assumption was the rebased patch number should
>> be equal to the corresponding number in the last report plus the added
>> patches in this report less the upstreamed patches in this report, i.e.,
>>
>> r = r_old + a - u
>>
>> where r and r_old are the current and last reported rebased patch numbers and a and u
>> are the current added and upstreamed patch numbers.
>>
>> But looking at the last several reports that formula predicts
>> incorrect results with the rebased patch number changing in what looks
>> like a completely arbitrary way from report to report compared to the
>> prediction. So it appears the above formula is incorrect and/or
>> incomplete.
>>
>> Could you let me know what the correct formula is for predicting the
>> rebased patch number from report to report (which helps to evaluate
>> the reliability of the staging patch number statistics that you
>> present), and if that formula depends on information (my guess is it
>> is the number of patches in staging that have just been deleted by the
>> staging maintainers because they judge those patches to not be
>> worthwhile) that you currently do not include in your reports, could
>> you include that important information in your following reports?
>
> In this case, I guess the confusion is caused by the fact that bugs
> 48175 and 46568 are addressed by the same patch set (viz.
> ntdll-ForceBottomUpAlloc). I suspect it may be better (or at least more
> consistent) to list the patch name first, followed by the bug(s) it
> addresses. We could also list the relevant bugs under the "updated" and
> "removed" sections.
The other cause for confusion, it occurs, is that 833 is the number of
individual patches, but these are organized into series, and the latter
are what are given symbolic names.
>
>>
>> TIA.
>>
>> Alan
>> __________________________
>> Alan W. Irwin
>>
>> Programming affiliations with the FreeEOS equation-of-state
>> implementation for stellar interiors (freeeos.sf.net) the Time
>> Ephemerides project (timeephem.sf.net) PLplot scientific plotting
>> software package (plplot.org) the libLASi project
>> (unifont.org/lasi) the Loads of Linux Links project (loll.sf.net)
>> and the Linux Brochure Project (lbproject.sf.net)
>> __________________________
>>
>> Linux-powered Science
>> __________________________
>>
>
Dec. 5, 2019
Re: [wine-devel] Wine staging 4.21 release
by Zebediah Figura
On 12/4/19 4:56 PM, Alan W. Irwin wrote:
> On 2019-11-30 04:56-0000 Alistair Leslie-Hughes wrote:
>
>> Binary packages for various distributions will be available from:
>> https://www.winehq.org/download
>>
>> Summary since last release
>> * Rebased to current wine 4.21 (833 patches are applied to wine vanilla)
>>
>> Upstreamed (Either directly from staging or fixed with a similar patch).
>> * none
>>
>> Added:
>> * [47668] kernelbase: Improve stub for ReOpenFile and add small test
>> * [48138] League of Legends 9.23: Crash after champ select
>> * [47970] Legends of Runeterra crashes at launch
>> * [40334] AION - Wine /Unhandled exception: page fault on read access to
>> 0x00000000 in 64-bit code (0x0000000000000000).
>> * [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high
>> memory pointers allocated
>> * [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist
>> package fails to load (Wine doesn't respect 44-bit user-mode VA
>> limitation from Windows < 8.1)
>>
>> Updated:
>> * d3d9-Direct3DShaderValidatorCreate9
>> * winecfg-Staging
>
> [...]
>
> Hi Alistair:
>
> Could you explain how these patch numbers in your report are related with each other?
> For example, my initial assumption was the rebased patch number should
> be equal to the corresponding number in the last report plus the added
> patches in this report less the upstreamed patches in this report, i.e.,
>
> r = r_old + a - u
>
> where r and r_old are the current and last reported rebased patch numbers and a and u
> are the current added and upstreamed patch numbers.
>
> But looking at the last several reports that formula predicts
> incorrect results with the rebased patch number changing in what looks
> like a completely arbitrary way from report to report compared to the
> prediction. So it appears the above formula is incorrect and/or
> incomplete.
>
> Could you let me know what the correct formula is for predicting the
> rebased patch number from report to report (which helps to evaluate
> the reliability of the staging patch number statistics that you
> present), and if that formula depends on information (my guess is it
> is the number of patches in staging that have just been deleted by the
> staging maintainers because they judge those patches to not be
> worthwhile) that you currently do not include in your reports, could
> you include that important information in your following reports?
In this case, I guess the confusion is caused by the fact that bugs
48175 and 46568 are addressed by the same patch set (viz.
ntdll-ForceBottomUpAlloc). I suspect it may be better (or at least more
consistent) to list the patch name first, followed by the bug(s) it
addresses. We could also list the relevant bugs under the "updated" and
"removed" sections.
>
> TIA.
>
> Alan
> __________________________
> Alan W. Irwin
>
> Programming affiliations with the FreeEOS equation-of-state
> implementation for stellar interiors (freeeos.sf.net) the Time
> Ephemerides project (timeephem.sf.net) PLplot scientific plotting
> software package (plplot.org) the libLASi project
> (unifont.org/lasi) the Loads of Linux Links project (loll.sf.net)
> and the Linux Brochure Project (lbproject.sf.net)
> __________________________
>
> Linux-powered Science
> __________________________
>
Dec. 5, 2019
[PATCH] jscript: Import to_int32 implementation from WebKit.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/jscript/jsutils.c | 63 +++++++++++++++++++++++++++++++++---------
1 file changed, 50 insertions(+), 13 deletions(-)
Dec. 5, 2019
[PATCH vkd3d v3 5/5] vkd3d: Implement support for D3D12_FEATURE_COMMAND_QUEUE_PRIORITY.
by Conor McCarthy
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
include/vkd3d_d3d12.idl | 7 +++++++
libs/vkd3d/device.c | 26 ++++++++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl
index 60f36b4..6e674a0 100644
--- a/include/vkd3d_d3d12.idl
+++ b/include/vkd3d_d3d12.idl
@@ -1654,6 +1654,13 @@ typedef struct D3D12_FEATURE_DATA_SHADER_CACHE
D3D12_SHADER_CACHE_SUPPORT_FLAGS SupportFlags;
} D3D12_FEATURE_DATA_SHADER_CACHE;
+typedef struct D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY
+{
+ D3D12_COMMAND_LIST_TYPE CommandListType;
+ UINT Priority;
+ BOOL PriorityForTypeIsSupported;
+} D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY;
+
typedef enum D3D12_FEATURE
{
D3D12_FEATURE_D3D12_OPTIONS = 0,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 694c322..8bae29d 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2785,6 +2785,32 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
return S_OK;
}
+ case D3D12_FEATURE_COMMAND_QUEUE_PRIORITY:
+ {
+ D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ switch (data->CommandListType)
+ {
+ case D3D12_COMMAND_LIST_TYPE_DIRECT:
+ case D3D12_COMMAND_LIST_TYPE_COMPUTE:
+ case D3D12_COMMAND_LIST_TYPE_COPY:
+ data->PriorityForTypeIsSupported = FALSE;
+ TRACE("Command list type %#x, priority %u, supported %#x.\n",
+ data->CommandListType, data->Priority, data->PriorityForTypeIsSupported);
+ return S_OK;
+
+ default:
+ FIXME("Unhandled command list type %#x.\n", data->CommandListType);
+ return E_INVALIDARG;
+ }
+ }
+
default:
FIXME("Unhandled feature %#x.\n", feature);
return E_NOTIMPL;
--
2.24.0
Dec. 5, 2019
[PATCH vkd3d v3 4/5] vkd3d: Implement support for D3D12_FEATURE_SHADER_CACHE.
by Conor McCarthy
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
include/vkd3d_d3d12.idl | 14 ++++++++++++++
libs/vkd3d/device.c | 19 +++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl
index 4c69454..60f36b4 100644
--- a/include/vkd3d_d3d12.idl
+++ b/include/vkd3d_d3d12.idl
@@ -184,6 +184,15 @@ typedef enum D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_2 = 0x2,
} D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER;
+typedef enum D3D12_SHADER_CACHE_SUPPORT_FLAGS
+{
+ D3D12_SHADER_CACHE_SUPPORT_NONE = 0x0,
+ D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO = 0x1,
+ D3D12_SHADER_CACHE_SUPPORT_LIBRARY = 0x2,
+ D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_INPROC_CACHE = 0x4,
+ D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_DISK_CACHE = 0x8,
+} D3D12_SHADER_CACHE_SUPPORT_FLAGS;
+
interface ID3D12Fence;
interface ID3D12RootSignature;
interface ID3D12Heap;
@@ -1640,6 +1649,11 @@ typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS2
D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER ProgrammableSamplePositionsTier;
} D3D12_FEATURE_DATA_D3D12_OPTIONS2;
+typedef struct D3D12_FEATURE_DATA_SHADER_CACHE
+{
+ D3D12_SHADER_CACHE_SUPPORT_FLAGS SupportFlags;
+} D3D12_FEATURE_DATA_SHADER_CACHE;
+
typedef enum D3D12_FEATURE
{
D3D12_FEATURE_D3D12_OPTIONS = 0,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 1063680..694c322 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2766,6 +2766,25 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
return S_OK;
}
+ case D3D12_FEATURE_SHADER_CACHE:
+ {
+ D3D12_FEATURE_DATA_SHADER_CACHE *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ /* FIXME: The D3D12 documentation states that D3D12_SHADER_CACHE_SUPPORT_SINGLE_PSO is
+ * always supported, but the CachedPSO field of D3D12_GRAPHICS_PIPELINE_STATE_DESC is
+ * ignored and GetCachedBlob() is a stub. */
+ data->SupportFlags = D3D12_SHADER_CACHE_SUPPORT_NONE;
+
+ TRACE("Shader cache support %#x.\n", data->SupportFlags);
+ return S_OK;
+ }
+
default:
FIXME("Unhandled feature %#x.\n", feature);
return E_NOTIMPL;
--
2.24.0
Dec. 5, 2019
[PATCH vkd3d v3 3/5] vkd3d: Implement support for D3D12_FEATURE_D3D12_OPTIONS2.
by Conor McCarthy
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
include/vkd3d_d3d12.idl | 13 +++++++++++++
libs/vkd3d/device.c | 22 ++++++++++++++++++++++
libs/vkd3d/vkd3d_private.h | 1 +
3 files changed, 36 insertions(+)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl
index ec102a8..4c69454 100644
--- a/include/vkd3d_d3d12.idl
+++ b/include/vkd3d_d3d12.idl
@@ -177,6 +177,13 @@ typedef enum D3D12_FORMAT_SUPPORT2
D3D12_FORMAT_SUPPORT2_MULTIPLANE_OVERLAY = 0x00004000,
} D3D12_FORMAT_SUPPORT2;
+typedef enum D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER
+{
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED = 0x0,
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_1 = 0x1,
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_2 = 0x2,
+} D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER;
+
interface ID3D12Fence;
interface ID3D12RootSignature;
interface ID3D12Heap;
@@ -1627,6 +1634,12 @@ typedef struct D3D12_FEATURE_DATA_ARCHITECTURE1
BOOL IsolatedMMU;
} D3D12_FEATURE_DATA_ARCHITECTURE1;
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS2
+{
+ BOOL DepthBoundsTestSupported;
+ D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER ProgrammableSamplePositionsTier;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS2;
+
typedef enum D3D12_FEATURE
{
D3D12_FEATURE_D3D12_OPTIONS = 0,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index dc8ca44..1063680 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1343,6 +1343,11 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
device->feature_options1.ExpandedComputeResourceStates = TRUE;
device->feature_options1.Int64ShaderOps = features->shaderInt64;
+ /* Depth bounds test is enabled in D3D12_DEPTH_STENCIL_DESC1, which is not supported. */
+ device->feature_options2.DepthBoundsTestSupported = FALSE;
+ /* d3d12_command_list_SetSamplePositions() is not implemented. */
+ device->feature_options2.ProgrammableSamplePositionsTier = D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER_NOT_SUPPORTED;
+
if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
{
ERR("Failed to enumerate device extensions, vr %d.\n", vr);
@@ -2744,6 +2749,23 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
return S_OK;
}
+ case D3D12_FEATURE_D3D12_OPTIONS2:
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS2 *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ *data = device->feature_options2;
+
+ TRACE("Depth bounds test %#x.\n", data->DepthBoundsTestSupported);
+ TRACE("Programmable sample positions tier %#x.\n", data->ProgrammableSamplePositionsTier);
+ return S_OK;
+ }
+
default:
FIXME("Unhandled feature %#x.\n", feature);
return E_NOTIMPL;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 6c7ec4e..72a7913 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -1135,6 +1135,7 @@ struct d3d12_device
D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options;
D3D12_FEATURE_DATA_D3D12_OPTIONS1 feature_options1;
+ D3D12_FEATURE_DATA_D3D12_OPTIONS2 feature_options2;
struct vkd3d_vulkan_info vk_info;
--
2.24.0
Dec. 5, 2019
[PATCH vkd3d v3 2/5] vkd3d: Implement support for D3D12_FEATURE_ARCHITECTURE1.
by Conor McCarthy
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
include/vkd3d_d3d12.idl | 9 +++++++++
libs/vkd3d/device.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl
index 5cfb229..ec102a8 100644
--- a/include/vkd3d_d3d12.idl
+++ b/include/vkd3d_d3d12.idl
@@ -1618,6 +1618,15 @@ typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS1
BOOL Int64ShaderOps;
} D3D12_FEATURE_DATA_D3D12_OPTIONS1;
+typedef struct D3D12_FEATURE_DATA_ARCHITECTURE1
+{
+ UINT NodeIndex;
+ BOOL TileBasedRenderer;
+ BOOL UMA;
+ BOOL CacheCoherentUMA;
+ BOOL IsolatedMMU;
+} D3D12_FEATURE_DATA_ARCHITECTURE1;
+
typedef enum D3D12_FEATURE
{
D3D12_FEATURE_D3D12_OPTIONS = 0,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 90044ac..dc8ca44 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2713,6 +2713,37 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
return S_OK;
}
+ case D3D12_FEATURE_ARCHITECTURE1:
+ {
+ D3D12_FEATURE_DATA_ARCHITECTURE1 *data = feature_data;
+ bool coherent;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ if (data->NodeIndex)
+ {
+ FIXME("Multi-adapter not supported.\n");
+ return E_INVALIDARG;
+ }
+
+ WARN("Assuming device does not support tile based rendering.\n");
+ data->TileBasedRenderer = FALSE;
+
+ data->UMA = d3d12_device_is_uma(device, &coherent);
+ data->CacheCoherentUMA = data->UMA ? coherent : FALSE;
+
+ WARN("Assuming device does not have an isolated memory management unit.\n");
+ data->IsolatedMMU = FALSE;
+
+ TRACE("Tile based renderer %#x, UMA %#x, cache coherent UMA %#x, isolated MMU %#x.\n",
+ data->TileBasedRenderer, data->UMA, data->CacheCoherentUMA, data->IsolatedMMU);
+ return S_OK;
+ }
+
default:
FIXME("Unhandled feature %#x.\n", feature);
return E_NOTIMPL;
--
2.24.0
Dec. 5, 2019
[PATCH vkd3d v3 1/5] vkd3d: Implement support for D3D12_FEATURE_D3D12_OPTIONS1.
by Conor McCarthy
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
include/vkd3d_d3d12.idl | 10 ++++++++++
libs/vkd3d/device.c | 28 ++++++++++++++++++++++++++++
libs/vkd3d/vkd3d_private.h | 1 +
3 files changed, 39 insertions(+)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl
index ec8b83d..5cfb229 100644
--- a/include/vkd3d_d3d12.idl
+++ b/include/vkd3d_d3d12.idl
@@ -1608,6 +1608,16 @@ typedef struct D3D12_FEATURE_DATA_SHADER_MODEL
D3D_SHADER_MODEL HighestShaderModel;
} D3D12_FEATURE_DATA_SHADER_MODEL;
+typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS1
+{
+ BOOL WaveOps;
+ UINT WaveLaneCountMin;
+ UINT WaveLaneCountMax;
+ UINT TotalLaneCount;
+ BOOL ExpandedComputeResourceStates;
+ BOOL Int64ShaderOps;
+} D3D12_FEATURE_DATA_D3D12_OPTIONS1;
+
typedef enum D3D12_FEATURE
{
D3D12_FEATURE_D3D12_OPTIONS = 0,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index fd593bc..90044ac 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1336,6 +1336,13 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
device->feature_options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = FALSE;
device->feature_options.ResourceHeapTier = D3D12_RESOURCE_HEAP_TIER_2;
+ device->feature_options1.WaveOps = FALSE;
+ device->feature_options1.WaveLaneCountMin = 0;
+ device->feature_options1.WaveLaneCountMax = 0;
+ device->feature_options1.TotalLaneCount = 0;
+ device->feature_options1.ExpandedComputeResourceStates = TRUE;
+ device->feature_options1.Int64ShaderOps = features->shaderInt64;
+
if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0)
{
ERR("Failed to enumerate device extensions, vr %d.\n", vr);
@@ -2668,6 +2675,27 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device *
return S_OK;
}
+ case D3D12_FEATURE_D3D12_OPTIONS1:
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS1 *data = feature_data;
+
+ if (feature_data_size != sizeof(*data))
+ {
+ WARN("Invalid size %u.\n", feature_data_size);
+ return E_INVALIDARG;
+ }
+
+ *data = device->feature_options1;
+
+ TRACE("Wave ops %#x.\n", data->WaveOps);
+ TRACE("Min wave lane count %#x.\n", data->WaveLaneCountMin);
+ TRACE("Max wave lane count %#x.\n", data->WaveLaneCountMax);
+ TRACE("Total lane count %#x.\n", data->TotalLaneCount);
+ TRACE("Expanded compute resource states %#x.\n", data->ExpandedComputeResourceStates);
+ TRACE("Int64 shader ops %#x.\n", data->Int64ShaderOps);
+ return S_OK;
+ }
+
case D3D12_FEATURE_ROOT_SIGNATURE:
{
D3D12_FEATURE_DATA_ROOT_SIGNATURE *data = feature_data;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 28801ba..6c7ec4e 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -1134,6 +1134,7 @@ struct d3d12_device
PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback;
D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options;
+ D3D12_FEATURE_DATA_D3D12_OPTIONS1 feature_options1;
struct vkd3d_vulkan_info vk_info;
--
2.24.0
Dec. 5, 2019
[PATCH vkd3d v3 0/5] Add more features to CheckFeatureSupport().
by Conor McCarthy
Some games, e.g. Shadow of the Tomb Raider, do not check for success,
and if the feature check is unimplemented they will use uninitialised
data for the result.
Supersedes 174666.
Conor McCarthy (5):
vkd3d: Implement support for D3D12_FEATURE_D3D12_OPTIONS1.
vkd3d: Implement support for D3D12_FEATURE_ARCHITECTURE1.
vkd3d: Implement support for D3D12_FEATURE_D3D12_OPTIONS2.
vkd3d: Implement support for D3D12_FEATURE_SHADER_CACHE.
vkd3d: Implement support for D3D12_FEATURE_COMMAND_QUEUE_PRIORITY.
include/vkd3d_d3d12.idl | 53 ++++++++++++++++
libs/vkd3d/device.c | 126 +++++++++++++++++++++++++++++++++++++
libs/vkd3d/vkd3d_private.h | 2 +
3 files changed, 181 insertions(+)
--
2.24.0
Dec. 5, 2019
[PATCH 2/2] kernel32/tests: Add a basic test for PROC_THREAD_ATTRIBUTE_PARENT_PROCESS process creation attribute.
by Paul Gofman
Signed-off-by: Paul Gofman <gofmanp(a)gmail.com>
---
dlls/kernel32/tests/process.c | 126 +++++++++++++++++++++++++++++++++-
1 file changed, 124 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index f181536e7a..a3118d11bf 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -36,6 +36,7 @@
#include "tlhelp32.h"
#include "wine/test.h"
+#include "wine/heap.h"
/* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
#define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
@@ -3808,6 +3809,120 @@ static void test_ProcThreadAttributeList(void)
pDeleteProcThreadAttributeList(&list);
}
+/* level 0: Main test process
+ * level 1: Process created by level 0 process without handle inheritance
+ * level 2: Process created by level 1 process with handle inheritance and level 0
+ * process parent substitute. */
+void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
+{
+ PROCESS_BASIC_INFORMATION pbi;
+ char buffer[MAX_PATH + 64];
+ HANDLE write_pipe = NULL;
+ PROCESS_INFORMATION info;
+ SECURITY_ATTRIBUTES sa;
+ STARTUPINFOEXA si;
+ DWORD parent_id;
+ NTSTATUS status;
+ ULONG pbi_size;
+ HANDLE parent;
+ DWORD size;
+ BOOL ret;
+
+ struct
+ {
+ HANDLE parent;
+ DWORD parent_id;
+ }
+ parent_data;
+
+ if (!pInitializeProcThreadAttributeList)
+ {
+ win_skip("No support for ProcThreadAttributeList.\n");
+ return;
+ }
+
+ memset(&sa, 0, sizeof(sa));
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+
+ if (!level)
+ {
+ ret = CreatePipe(&read_pipe, &write_pipe, &sa, 0);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+
+ parent_data.parent = OpenProcess(PROCESS_CREATE_PROCESS | PROCESS_QUERY_INFORMATION, TRUE, GetCurrentProcessId());
+ parent_data.parent_id = GetCurrentProcessId();
+ }
+ else
+ {
+ status = NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &pbi_size);
+ ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
+ parent_id = pbi.InheritedFromUniqueProcessId;
+
+ memset(&parent_data, 0, sizeof(parent_data));
+ ret = ReadFile(read_pipe, &parent_data, sizeof(parent_data), &size, NULL);
+ todo_wine_if(level == 2) ok((level == 2 && ret) || (level == 1 && !ret && GetLastError() == ERROR_INVALID_HANDLE),
+ "Got unexpected ret %#x, level %u, GetLastError() %u.\n",
+ ret, level, GetLastError());
+ }
+
+ if (level == 2)
+ {
+ todo_wine ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n",
+ parent_id, parent_data.parent_id);
+ return;
+ }
+
+ memset(&si, 0, sizeof(si));
+ si.StartupInfo.cb = sizeof(si.StartupInfo);
+
+ if (level)
+ {
+ SIZE_T size;
+
+ ret = pInitializeProcThreadAttributeList(NULL, 1, 0, &size);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ si.lpAttributeList = heap_alloc(size);
+ ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+
+ parent = OpenProcess(PROCESS_CREATE_PROCESS, FALSE, parent_id);
+
+ ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
+ &parent, sizeof(parent), NULL, NULL);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ }
+
+ sprintf(buffer, "\"%s\" tests/process.c parent %u %p", selfname, level + 1, read_pipe);
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, level == 1, level == 1 ? EXTENDED_STARTUPINFO_PRESENT : 0,
+ NULL, NULL, (STARTUPINFOA *)&si, &info);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+
+ if (level)
+ {
+ pDeleteProcThreadAttributeList(si.lpAttributeList);
+ heap_free(si.lpAttributeList);
+ CloseHandle(parent);
+ }
+ else
+ {
+ ret = WriteFile(write_pipe, &parent_data, sizeof(parent_data), &size, NULL);
+ }
+
+ /* wait for child to terminate */
+ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ CloseHandle(info.hThread);
+ CloseHandle(info.hProcess);
+
+ if (!level)
+ {
+ CloseHandle(read_pipe);
+ CloseHandle(write_pipe);
+ CloseHandle(parent_data.parent);
+ }
+}
+
START_TEST(process)
{
HANDLE job;
@@ -3851,11 +3966,18 @@ START_TEST(process)
CloseHandle(info.hThread);
return;
}
+ else if (!strcmp(myARGV[2], "parent") && myARGC >= 5)
+ {
+ HANDLE h;
+
+ sscanf(myARGV[4], "%p", &h);
+ test_parent_process_attribute(atoi(myARGV[3]), h);
+ return;
+ }
ok(0, "Unexpected command %s\n", myARGV[2]);
return;
}
-
hproc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId());
if (hproc)
{
@@ -3865,7 +3987,6 @@ START_TEST(process)
else
win_skip("PROCESS_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
test_process_info(GetCurrentProcess());
-
test_TerminateProcess();
test_Startup();
test_CommandLine();
@@ -3919,4 +4040,5 @@ START_TEST(process)
test_jobInheritance(job);
test_BreakawayOk(job);
CloseHandle(job);
+ test_parent_process_attribute(0, NULL);
}
--
2.23.0
Dec. 5, 2019
[PATCH 1/2] include/winbase.h: Add STARTUPINFOEX structure definition.
by Paul Gofman
Signed-off-by: Paul Gofman <gofmanp(a)gmail.com>
---
include/winbase.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/include/winbase.h b/include/winbase.h
index 2d01dcb606..71f7ea1586 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1736,6 +1736,19 @@ typedef enum _PROC_THREAD_ATTRIBUTE_NUM
#define SYMBOLIC_LINK_FLAG_DIRECTORY (0x1)
#define VALID_SYMBOLIC_LINK_FLAGS SYMBOLIC_LINK_FLAG_DIRECTORY
+typedef struct _STARTUPINFOEXA{
+ STARTUPINFOA StartupInfo;
+ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
+} STARTUPINFOEXA, *LPSTARTUPINFOEXA;
+
+typedef struct _STARTUPINFOEXW{
+ STARTUPINFOW StartupInfo;
+ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
+} STARTUPINFOEXW, *LPSTARTUPINFOEXW;
+
+DECL_WINELIB_TYPE_AW(STARTUPINFOEX)
+DECL_WINELIB_TYPE_AW(LPSTARTUPINFOEX)
+
typedef void *PUMS_CONTEXT;
typedef void *PUMS_COMPLETION_LIST;
typedef PRTL_UMS_SCHEDULER_ENTRY_POINT PUMS_SCHEDULER_ENTRY_POINT;
--
2.23.0
Dec. 5, 2019
Re: [wine-devel] Wine staging 4.21 release
by Olivier F. R. Dierick
Le mercredi 04 décembre 2019 à 14:56 -0800, Alan W. Irwin a écrit :
> On 2019-11-30 04:56-0000 Alistair Leslie-Hughes wrote:
>
> > Added:
> > * [47668] kernelbase: Improve stub for ReOpenFile and add small
> > test
> > * [48138] League of Legends 9.23: Crash after champ select
> > * [47970] Legends of Runeterra crashes at launch
> > * [40334] AION - Wine /Unhandled exception: page fault on read
> > access to
> > 0x00000000 in 64-bit code (0x0000000000000000).
> > * [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to
> > high
> > memory pointers allocated
> > * [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0
> > redist
> > package fails to load (Wine doesn't respect 44-bit user-mode VA
> > limitation from Windows < 8.1)
> >
> [...]
>
> Could you explain how these patch numbers in your report are related
> with each other?
>
Hello,
The numbers between brackets are winehq.org bugzilla bug numbers.
For example, in "[47668] kernelbase: Improve stub for ReOpenFile and
add small test", "47668" is the bug number that the patch "kernelbase:
Improve stub for ReOpenFile" is accommodating. The referenced bug can
be found at the URL: https://bugs.winehq.org/show_bug.cgi?id=47668
Regards.
--
Olivier F. R. Dierick
o.dierick(a)piezo-forte.be
Dec. 5, 2019
[PATCH] tests: Trace elapsed time when $WINETEST_TIME is set.
by Francois Gouget
This simplifies narrowing down where a test gets stuck or is slow if
it times out but prints few messages.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48094
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
If this approach is acceptable I'll add support for it on the TestBot
and on the test.winehq.org site: allowing to set $WINETEST_TIME and
recognizing the modified failure lines.
include/wine/test.h | 72 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 17 deletions(-)
diff --git a/include/wine/test.h b/include/wine/test.h
index aeb9a55dee2..dea94fa60f0 100644
--- a/include/wine/test.h
+++ b/include/wine/test.h
@@ -58,6 +58,9 @@
/* debug level */
extern int winetest_debug;
+/* trace timing information */
+extern int winetest_time;
+
/* running in interactive mode? */
extern int winetest_interactive;
@@ -216,6 +219,10 @@ extern const struct test winetest_testlist[];
/* debug level */
int winetest_debug = 1;
+/* trace timing information */
+int winetest_time = 0;
+DWORD winetest_start_time, winetest_last_time;
+
/* interactive mode? */
int winetest_interactive = 0;
@@ -304,11 +311,27 @@ void winetest_set_location( const char* file, int line )
data->current_line=line;
}
+const char *winetest_elapsed(void)
+{
+ DWORD now;
+ char *res;
+
+ if (!winetest_time)
+ return "";
+
+ now = GetTickCount();
+ winetest_last_time = now;
+ res = get_temp_buffer( 11 ); /* enough for a day */
+ sprintf( res, "%.3f", (now - winetest_start_time) / 1000.0);
+ release_temp_buffer( res, strlen(res) + 1 );
+ return res;
+}
+
void winetest_subtest( const char* name )
{
struct tls_data *data = get_tls_data();
- printf( "%s:%d: Subtest %s\n",
- data->current_file, data->current_line, name);
+ printf( "%s:%d:%s Subtest %s\n",
+ data->current_file, data->current_line, name, winetest_elapsed());
}
int broken( int condition )
@@ -334,8 +357,8 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
{
if (condition)
{
- printf( "%s:%d: Test succeeded inside todo block: ",
- data->current_file, data->current_line );
+ printf( "%s:%d:%s Test succeeded inside todo block: ",
+ data->current_file, data->current_line, winetest_elapsed() );
vprintf(msg, args);
InterlockedIncrement(&todo_failures);
return 0;
@@ -344,8 +367,8 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
{
if (winetest_debug > 0)
{
- printf( "%s:%d: Test marked todo: ",
- data->current_file, data->current_line );
+ printf( "%s:%d:%s Test marked todo: ",
+ data->current_file, data->current_line, winetest_elapsed() );
vprintf(msg, args);
}
InterlockedIncrement(&todo_successes);
@@ -356,17 +379,20 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
{
if (!condition)
{
- printf( "%s:%d: Test failed: ",
- data->current_file, data->current_line );
+ printf( "%s:%d:%s Test failed: ",
+ data->current_file, data->current_line, winetest_elapsed() );
vprintf(msg, args);
InterlockedIncrement(&failures);
return 0;
}
else
{
- if (winetest_report_success)
- printf( "%s:%d: Test succeeded\n",
- data->current_file, data->current_line);
+ if (winetest_report_success ||
+ (winetest_time && GetTickCount() >= winetest_last_time + 1000))
+ {
+ printf( "%s:%d:%s Test succeeded\n",
+ data->current_file, data->current_line, winetest_elapsed() );
+ }
InterlockedIncrement(&successes);
return 1;
}
@@ -389,7 +415,7 @@ void __winetest_cdecl winetest_trace( const char *msg, ... )
if (winetest_debug > 0)
{
- printf( "%s:%d: ", data->current_file, data->current_line );
+ printf( "%s:%d:%s ", data->current_file, data->current_line, winetest_elapsed() );
__winetest_va_start(valist, msg);
vprintf(msg, valist);
__winetest_va_end(valist);
@@ -400,7 +426,7 @@ void winetest_vskip( const char *msg, __winetest_va_list args )
{
struct tls_data *data = get_tls_data();
- printf( "%s:%d: Tests skipped: ", data->current_file, data->current_line );
+ printf( "%s:%d:%s Tests skipped: ", data->current_file, data->current_line, winetest_elapsed() );
vprintf(msg, args);
skipped++;
}
@@ -630,8 +656,8 @@ static int run_test( const char *name )
if (winetest_debug)
{
- printf( "%04x:%s: %d tests executed (%d marked as todo, %d %s), %d skipped.\n",
- GetCurrentProcessId(), test->name,
+ printf( "%04x:%s:%s %d tests executed (%d marked as todo, %d %s), %d skipped.\n",
+ GetCurrentProcessId(), test->name, winetest_elapsed(),
successes + failures + todo_successes + todo_failures,
todo_successes, failures + todo_failures,
(failures + todo_failures != 1) ? "failures" : "failure",
@@ -656,8 +682,8 @@ static LONG CALLBACK exc_filter( EXCEPTION_POINTERS *ptrs )
struct tls_data *data = get_tls_data();
if (data->current_file)
- printf( "%s:%d: this is the last test seen before the exception\n",
- data->current_file, data->current_line );
+ printf( "%s:%d:%s this is the last test seen before the exception\n",
+ data->current_file, data->current_line, winetest_elapsed() );
printf( "%04x:%s: unhandled exception %08x at %p\n",
GetCurrentProcessId(), current_test->name,
ptrs->ExceptionRecord->ExceptionCode, ptrs->ExceptionRecord->ExceptionAddress );
@@ -695,6 +721,18 @@ int main( int argc, char **argv )
if (GetEnvironmentVariableA( "WINETEST_DEBUG", p, sizeof(p) )) winetest_debug = atoi(p);
if (GetEnvironmentVariableA( "WINETEST_INTERACTIVE", p, sizeof(p) )) winetest_interactive = atoi(p);
if (GetEnvironmentVariableA( "WINETEST_REPORT_SUCCESS", p, sizeof(p) )) winetest_report_success = atoi(p);
+ if (GetEnvironmentVariableA( "WINETEST_TIME", p, sizeof(p) )) winetest_time = atoi(p);
+ if (GetEnvironmentVariableA( "WINETEST_START_TIME", p, sizeof(p) ))
+ winetest_start_time = atoi(p);
+ else
+ {
+ char time_str[11];
+ winetest_start_time = GetTickCount();
+ /* Export the test start time for child processes */
+ sprintf( time_str, "%u", winetest_start_time );
+ SetEnvironmentVariableA( "WINETEST_START_TIME", time_str );
+ }
+ winetest_last_time = winetest_start_time;
if (!strcmp( winetest_platform, "windows" )) SetUnhandledExceptionFilter( exc_filter );
if (!winetest_interactive) SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX );
--
2.20.1
Dec. 5, 2019
[PATCH] testbot/LogUtils: GetLogFileNames() should untaint the returned log names.
by Francois Gouget
Otherwise the caller may get an error when trying to use them for file
operations (such as unlink).
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/LogUtils.pm | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/testbot/lib/WineTestBot/LogUtils.pm b/testbot/lib/WineTestBot/LogUtils.pm
index 32bf0fa61..4a17857f8 100644
--- a/testbot/lib/WineTestBot/LogUtils.pm
+++ b/testbot/lib/WineTestBot/LogUtils.pm
@@ -634,13 +634,21 @@ sub GetLogFileNames($;$)
foreach my $FileName (glob("'$Dir/$Glob*'"))
{
my $LogName = basename($FileName);
- if ($LogName !~ s/\.err$// and $LogName !~ /\.report$/ and
- $LogName ne $Glob) # 'log' case
+ $LogName =~ s/\.err$//;
+ next if ($Seen{$LogName});
+ if ($LogName =~ /^([a-zA-Z0-9_]+\.report)$/)
+ {
+ $LogName = $1; # untaint
+ }
+ elsif ($LogName eq $Glob) # log and old_log cases
+ {
+ $LogName = $Glob; # untaint
+ }
+ else
{
# Not a valid log filename (where does this file come from?)
next;
}
- next if ($Seen{$LogName});
$Seen{$LogName} = 1;
if ((-f "$Dir/$LogName" and !-z "$Dir/$LogName") or
--
2.20.1
Dec. 5, 2019
[PATCH] testbot/WineSendLog: Errors are not new when missing reference reports.
by Francois Gouget
Build logs don't have reference logs so for them every error is new.
But test reports should have reference WineTest results and if not
reporting the errors as new would cause false positives. So default
to "not new" in that case.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/WineSendLog.pl | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/testbot/bin/WineSendLog.pl b/testbot/bin/WineSendLog.pl
index 721122edb..95cc036c9 100755
--- a/testbot/bin/WineSendLog.pl
+++ b/testbot/bin/WineSendLog.pl
@@ -291,8 +291,11 @@ EOF
my ($NewGroups, $NewErrors, $_NewIndices) = GetNewLogErrors($RefFileName, $LogErrors->{Groups}, $LogErrors->{Errors});
if (!$NewGroups)
{
- # There was no reference log (typical of build logs)
- # so every error is new
+ # Test reports should have reference WineTest results and if not
+ # reporting the errors as new would cause false positives.
+ next if ($LogName =~ /\.report$/);
+
+ # Build logs don't have reference logs so for them every error is new.
$NewGroups = $LogErrors->{Groups};
$NewErrors = $LogErrors->{Errors};
}
--
2.20.1
Dec. 5, 2019
[PATCH] testbot/Janitor: Fix extracting the VM name from reference report filenames.
by Francois Gouget
The log name part can contain underscores and uppercase letters when
testing locales.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/Janitor.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testbot/bin/Janitor.pl b/testbot/bin/Janitor.pl
index 537a0dc4a..c51637a19 100755
--- a/testbot/bin/Janitor.pl
+++ b/testbot/bin/Janitor.pl
@@ -308,7 +308,7 @@ if (opendir(my $dh, "$DataDir/latest"))
{
next if ($Entry eq "." or $Entry eq "..");
- if ($Entry =~ /^(.*)_[a-z0-9]+\.report(?:\.err)?$/)
+ if ($Entry =~ /^([a-zA-Z0-9_]+)_(?:exe|win|wow)(?:32|64)[a-zA-Z0-9_]*\.report(?:\.err)?$/)
{
# Keep the reference WineTest reports for all VMs even if they are
# retired or scheduled for deletion.
--
2.20.1
Dec. 5, 2019
Re: [PATCH] msxml3: all string passed to IXMLDOMDocument_load() need to be URL-unescaped
by Nikolay Sivov
Do we need to unescape if it's not a file:// url?I was hoping we could
find some IUri/path API flags to do what we need for us.
Another concern is path/url max lengths are used seemingly randomly, and
it's not a problem with your change, but with existing code.I think
asking for required length and allocating it is better.
> + /* Regular local path with some URL encoded characters. */
> + strcpy(path2, path);
> + n = strlen(path2);
> + path2[n-1] = '%';
> + path2[n] = '6';
> + path2[n+1] = 'C';
> + path2[n+2] = '\0'; /* C:\path\to\winetest.xm%6C */
> + test_doc_load_from_path(doc, path2);
Could you make this more readable? Maybe strcat-ing escaped file name as
string literal instead.
> + /* Regular local path with all URL encoded characters. */
> + percent_path = HeapAlloc(GetProcessHeap(), 0, 3*n + 1);
> + for (i = 0; i < n; i++)
> + {
> + static char hex_tab[] = "0123456789ABCDEF";
> + percent_path[3*i] = '%';
> + percent_path[3*i + 1] = hex_tab[path[i] >> 4];
> + percent_path[3*i + 2] = hex_tab[path[i] & 0xF];
> + }
> + percent_path[3*n] = '\0';
> + test_doc_load_from_path(doc, percent_path);
> + HeapFree(GetProcessHeap(), 0, percent_path);
Couple of cases would be enough, like you did earlier for "l" -> %6c,
and another one for " " -> %20. Space is actually not tested by this
patch, and that's what application is using. If you still want to encode
it entirely, please add a helper function.
Dec. 5, 2019
[PATCH vkd3d v3] vkd3d: Add a memory usage info callback optional extension.
by Conor McCarthy
Allows memory usage info to be sent to Wine DXGI.
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
Supersedes 173692.
v3: Remove total memory from the function parameters.
---
include/vkd3d.h | 12 ++++++++++++
libs/vkd3d/command.c | 6 +++---
libs/vkd3d/device.c | 14 +++++++++++++-
libs/vkd3d/resource.c | 19 +++++++++++++------
libs/vkd3d/vkd3d_private.h | 20 ++++++++++++++++++++
5 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/include/vkd3d.h b/include/vkd3d.h
index e2d9ec8..17c07d1 100644
--- a/include/vkd3d.h
+++ b/include/vkd3d.h
@@ -47,6 +47,7 @@ enum vkd3d_structure_type
/* 1.2 */
VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO,
VKD3D_STRUCTURE_TYPE_APPLICATION_INFO,
+ VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_CALLBACK_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE),
};
@@ -129,6 +130,17 @@ struct vkd3d_optional_device_extensions_info
uint32_t extension_count;
};
+typedef void (STDMETHODCALLTYPE *PFN_vkd3d_memory_usage_callback)(IUnknown *adapter,
+ unsigned int non_local, INT64 change);
+
+struct vkd3d_optional_device_callback_info
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+
+ PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback;
+};
+
/* vkd3d_image_resource_create_info flags */
#define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
#define VKD3D_RESOURCE_PRESENT_STATE_TRANSITION 0x00000002
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 75af27d..1b62f9a 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -1416,7 +1416,7 @@ static void vkd3d_buffer_destroy(struct vkd3d_buffer *buffer, struct d3d12_devic
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
- VK_CALL(vkFreeMemory(device->vk_device, buffer->vk_memory, NULL));
+ vkd3d_free_device_memory(device, buffer->vk_memory_type, buffer->vk_memory_size, buffer->vk_memory);
VK_CALL(vkDestroyBuffer(device->vk_device, buffer->vk_buffer, NULL));
}
@@ -3232,8 +3232,8 @@ static HRESULT d3d12_command_list_allocate_transfer_buffer(struct d3d12_command_
if (FAILED(hr = vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
&buffer_desc, &buffer->vk_buffer)))
return hr;
- if (FAILED(hr = vkd3d_allocate_buffer_memory(device, buffer->vk_buffer,
- &heap_properties, D3D12_HEAP_FLAG_NONE, &buffer->vk_memory, NULL, NULL)))
+ if (FAILED(hr = vkd3d_allocate_buffer_memory(device, buffer->vk_buffer, &heap_properties,
+ D3D12_HEAP_FLAG_NONE, &buffer->vk_memory, &buffer->vk_memory_type, &buffer->vk_memory_size)))
{
VK_CALL(vkDestroyBuffer(device->vk_device, buffer->vk_buffer, NULL));
return hr;
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index e3bb2aa..fd593bc 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -3390,6 +3390,7 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface)
static HRESULT d3d12_device_init(struct d3d12_device *device,
struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info)
{
+ const struct vkd3d_optional_device_callback_info *optional_callback;
const struct vkd3d_vk_device_procs *vk_procs;
HRESULT hr;
size_t i;
@@ -3407,6 +3408,17 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
device->vk_device = VK_NULL_HANDLE;
+ device->parent = create_info->parent;
+
+ device->pfn_memory_usage_callback = NULL;
+ optional_callback = vkd3d_find_struct(create_info->next, OPTIONAL_DEVICE_CALLBACK_INFO);
+ if (optional_callback)
+ {
+ device->pfn_memory_usage_callback = optional_callback->pfn_memory_usage_callback;
+ if (device->pfn_memory_usage_callback)
+ TRACE("Found memory callback function %p.\n", device->pfn_memory_usage_callback);
+ }
+
if (FAILED(hr = vkd3d_create_vk_device(device, create_info)))
goto out_free_instance;
@@ -3434,7 +3446,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i)
pthread_mutex_init(&device->desc_mutex[i], NULL);
- if ((device->parent = create_info->parent))
+ if (device->parent)
IUnknown_AddRef(device->parent);
return S_OK;
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index f40d986..f5fccfa 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -147,6 +147,8 @@ static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device,
if (vk_memory_type)
*vk_memory_type = allocate_info.memoryTypeIndex;
+ d3d12_device_update_memory_usage(device, allocate_info.memoryTypeIndex, allocate_info.allocationSize);
+
return S_OK;
}
@@ -161,6 +163,7 @@ HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_bu
VkMemoryRequirements2 memory_requirements2;
VkMemoryRequirements *memory_requirements;
VkBufferMemoryRequirementsInfo2 info;
+ uint32_t type;
VkResult vr;
HRESULT hr;
@@ -196,16 +199,18 @@ HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_bu
}
if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
- memory_requirements, dedicated_allocation, vk_memory, vk_memory_type)))
+ memory_requirements, dedicated_allocation, vk_memory, &type)))
return hr;
if ((vr = VK_CALL(vkBindBufferMemory(device->vk_device, vk_buffer, *vk_memory, 0))) < 0)
{
WARN("Failed to bind memory, vr %d.\n", vr);
- VK_CALL(vkFreeMemory(device->vk_device, *vk_memory, NULL));
+ vkd3d_free_device_memory(device, type, memory_requirements->size, *vk_memory);
*vk_memory = VK_NULL_HANDLE;
}
+ if (vk_memory_type)
+ *vk_memory_type = type;
if (vk_memory_size)
*vk_memory_size = memory_requirements->size;
@@ -223,6 +228,7 @@ static HRESULT vkd3d_allocate_image_memory(struct d3d12_device *device, VkImage
VkMemoryRequirements2 memory_requirements2;
VkMemoryRequirements *memory_requirements;
VkImageMemoryRequirementsInfo2 info;
+ uint32_t type;
VkResult vr;
HRESULT hr;
@@ -258,17 +264,19 @@ static HRESULT vkd3d_allocate_image_memory(struct d3d12_device *device, VkImage
}
if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
- memory_requirements, dedicated_allocation, vk_memory, vk_memory_type)))
+ memory_requirements, dedicated_allocation, vk_memory, &type)))
return hr;
if ((vr = VK_CALL(vkBindImageMemory(device->vk_device, vk_image, *vk_memory, 0))) < 0)
{
WARN("Failed to bind memory, vr %d.\n", vr);
- VK_CALL(vkFreeMemory(device->vk_device, *vk_memory, NULL));
+ vkd3d_free_device_memory(device, type, memory_requirements->size, *vk_memory);
*vk_memory = VK_NULL_HANDLE;
return hresult_from_vk_result(vr);
}
+ if (vk_memory_type)
+ *vk_memory_type = type;
if (vk_memory_size)
*vk_memory_size = memory_requirements->size;
@@ -318,13 +326,12 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface)
static void d3d12_heap_destroy(struct d3d12_heap *heap)
{
struct d3d12_device *device = heap->device;
- const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
TRACE("Destroying heap %p.\n", heap);
vkd3d_private_store_destroy(&heap->private_store);
- VK_CALL(vkFreeMemory(device->vk_device, heap->vk_memory, NULL));
+ vkd3d_free_device_memory(device, heap->vk_memory_type, heap->desc.SizeInBytes, heap->vk_memory);
pthread_mutex_destroy(&heap->mutex);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 9ff6bba..28801ba 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -839,6 +839,8 @@ struct vkd3d_buffer
{
VkBuffer vk_buffer;
VkDeviceMemory vk_memory;
+ VkDeviceSize vk_memory_size;
+ uint32_t vk_memory_type;
};
/* ID3D12CommandAllocator */
@@ -1129,6 +1131,7 @@ struct d3d12_device
VkPipelineCache vk_pipeline_cache;
VkPhysicalDeviceMemoryProperties memory_properties;
+ PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback;
D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options;
@@ -1199,6 +1202,23 @@ static inline pthread_mutex_t *d3d12_device_get_descriptor_mutex(struct d3d12_de
return &device->desc_mutex[idx & (ARRAY_SIZE(device->desc_mutex) - 1)];
}
+static inline void d3d12_device_update_memory_usage(struct d3d12_device *device, uint32_t vk_memory_type, int64_t change)
+{
+ unsigned int non_local = !(device->memory_properties.memoryTypes[vk_memory_type].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+
+ if (device->pfn_memory_usage_callback)
+ device->pfn_memory_usage_callback(device->parent, non_local, change);
+}
+
+static inline void vkd3d_free_device_memory(struct d3d12_device *device,
+ uint32_t type, VkDeviceSize size, VkDeviceMemory vk_memory)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+
+ VK_CALL(vkFreeMemory(device->vk_device, vk_memory, NULL));
+ d3d12_device_update_memory_usage(device, type, -(int64_t)size);
+}
+
/* utils */
enum vkd3d_format_type
{
--
2.24.0
Dec. 5, 2019
[PATCH 3/3] bcrypt: Add more BCryptSignHash tests.
by Hans Leidekker
From: Derek Lesho <dlesho(a)codeweavers.com>
v2: Verify signature.
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/bcrypt/tests/bcrypt.c | 49 ++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index d125e0c89d..198acbf721 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -2049,6 +2049,9 @@ static void test_BCryptSignHash(void)
{
static UCHAR hash[] =
{0x7e,0xe3,0x74,0xe7,0xc5,0x0b,0x6b,0x70,0xdb,0xab,0x32,0x6d,0x1d,0x51,0xd6,0x74,0x79,0x8e,0x5b,0x4b};
+ static UCHAR hash_sha256[] =
+ {0x25,0x2f,0x10,0xc8,0x36,0x10,0xeb,0xca,0x1a,0x05,0x9c,0x0b,0xae,0x82,0x55,0xeb,0xa2,0xf9,0x5b,0xe4,
+ 0xd1,0xd7,0xbC,0xfA,0x89,0xd7,0x24,0x8a,0x82,0xd9,0xf1,0x11};
BCRYPT_PKCS1_PADDING_INFO pad;
BCRYPT_ALG_HANDLE alg;
BCRYPT_KEY_HANDLE key;
@@ -2056,6 +2059,8 @@ static void test_BCryptSignHash(void)
NTSTATUS ret;
ULONG len;
+ /* RSA */
+
ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_RSA_ALGORITHM, NULL, 0);
if (ret)
{
@@ -2087,6 +2092,14 @@ static void test_BCryptSignHash(void)
len = 0;
memset(sig, 0, sizeof(sig));
+
+ /* inference of padding info on RSA not supported */
+ ret = pBCryptSignHash(key, NULL, hash, sizeof(hash), sig, sizeof(sig), &len, 0);
+ ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
+
+ ret = pBCryptSignHash(key, &pad, hash, sizeof(hash), sig, 0, &len, BCRYPT_PAD_PKCS1);
+ ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
+
ret = pBCryptSignHash(key, &pad, hash, sizeof(hash), sig, sizeof(sig), &len, BCRYPT_PAD_PKCS1);
ok(!ret, "got %08x\n", ret);
ok(len == 64, "got %u\n", len);
@@ -2099,6 +2112,42 @@ static void test_BCryptSignHash(void)
ret = pBCryptCloseAlgorithmProvider(alg, 0);
ok(!ret, "got %08x\n", ret);
+
+ /* ECDSA */
+
+ ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_ECDSA_P256_ALGORITHM, NULL, 0);
+ if (ret)
+ {
+ win_skip("failed to open ECDSA provider: %08x\n", ret);
+ return;
+ }
+
+ ret = pBCryptGenerateKeyPair(alg, &key, 256, 0);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+
+ ret = pBCryptFinalizeKeyPair(key, 0);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+
+ memset(sig, 0, sizeof(sig));
+ len = 0;
+
+ /* automatically detects padding info */
+ ret = pBCryptSignHash(key, NULL, hash, sizeof(hash), sig, sizeof(sig), &len, 0);
+ ok (!ret, "got %08x\n", ret);
+ ok (len == 64, "got %u\n", len);
+
+ ret = pBCryptVerifySignature(key, NULL, hash, sizeof(hash), sig, len, 0);
+ ok(!ret, "got %08x\n", ret);
+
+ /* mismatch info (SHA-1 != SHA-256) */
+ ret = pBCryptSignHash(key, &pad, hash_sha256, sizeof(hash_sha256), sig, sizeof(sig), &len, BCRYPT_PAD_PKCS1);
+ ok (ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
+
+ ret = pBCryptDestroyKey(key);
+ ok(!ret, "got %08x\n", ret);
+
+ ret = pBCryptCloseAlgorithmProvider(alg, 0);
+ ok(!ret, "got %08x\n", ret);
}
static void test_BCryptEnumAlgorithms(void)
--
2.20.1
Dec. 5, 2019
[PATCH 2/3] bcrypt: Handle SHA1 hash in key_asymmetric_verify.
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/bcrypt/gnutls.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 379d76a32e..2f048d6c86 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -1064,6 +1064,7 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
/* only the hash size must match, not the actual hash function */
switch (hash_len)
{
+ case 20: hash_alg = GNUTLS_DIG_SHA1; break;
case 32: hash_alg = GNUTLS_DIG_SHA256; break;
case 48: hash_alg = GNUTLS_DIG_SHA384; break;
--
2.20.1
Dec. 5, 2019
[PATCH 1/3] bcrypt: Add support for signing hashes with ECDSA keys.
by Hans Leidekker
From: Derek Lesho <dlesho(a)codeweavers.com>
v2: Avoid goto within switch statement, formatting.
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/bcrypt/gnutls.c | 147 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 130 insertions(+), 17 deletions(-)
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index a6a07fff19..379d76a32e 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -92,6 +92,7 @@ MAKE_FUNCPTR(gnutls_cipher_decrypt2);
MAKE_FUNCPTR(gnutls_cipher_deinit);
MAKE_FUNCPTR(gnutls_cipher_encrypt2);
MAKE_FUNCPTR(gnutls_cipher_init);
+MAKE_FUNCPTR(gnutls_decode_rs_value);
MAKE_FUNCPTR(gnutls_global_deinit);
MAKE_FUNCPTR(gnutls_global_init);
MAKE_FUNCPTR(gnutls_global_set_log_function);
@@ -189,6 +190,7 @@ BOOL gnutls_initialize(void)
LOAD_FUNCPTR(gnutls_cipher_deinit)
LOAD_FUNCPTR(gnutls_cipher_encrypt2)
LOAD_FUNCPTR(gnutls_cipher_init)
+ LOAD_FUNCPTR(gnutls_decode_rs_value)
LOAD_FUNCPTR(gnutls_global_deinit)
LOAD_FUNCPTR(gnutls_global_init)
LOAD_FUNCPTR(gnutls_global_set_log_function)
@@ -711,6 +713,7 @@ NTSTATUS key_asymmetric_generate( struct key *key )
break;
case ALG_ID_ECDH_P256:
+ case ALG_ID_ECDSA_P256:
pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */
bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1 );
break;
@@ -1029,6 +1032,17 @@ static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULO
}
}
+static gnutls_digest_algorithm_t get_digest_from_id( const WCHAR *alg_id )
+{
+ if (!strcmpW( alg_id, BCRYPT_SHA1_ALGORITHM )) return GNUTLS_DIG_SHA1;
+ if (!strcmpW( alg_id, BCRYPT_SHA256_ALGORITHM )) return GNUTLS_DIG_SHA256;
+ if (!strcmpW( alg_id, BCRYPT_SHA384_ALGORITHM )) return GNUTLS_DIG_SHA384;
+ if (!strcmpW( alg_id, BCRYPT_SHA512_ALGORITHM )) return GNUTLS_DIG_SHA512;
+ if (!strcmpW( alg_id, BCRYPT_MD2_ALGORITHM )) return GNUTLS_DIG_MD2;
+ if (!strcmpW( alg_id, BCRYPT_MD5_ALGORITHM )) return GNUTLS_DIG_MD5;
+ return -1;
+}
+
NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len, UCHAR *signature,
ULONG signature_len, DWORD flags )
{
@@ -1068,11 +1082,7 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
if (!(flags & BCRYPT_PAD_PKCS1) || !info) return STATUS_INVALID_PARAMETER;
if (!info->pszAlgId) return STATUS_INVALID_SIGNATURE;
- if (!strcmpW( info->pszAlgId, BCRYPT_SHA1_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA1;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA256_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA256;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA384_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA384;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA512_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA512;
- else
+ if ((hash_alg = get_digest_from_id(info->pszAlgId)) == -1)
{
FIXME( "hash algorithm %s not supported\n", debugstr_w(info->pszAlgId) );
return STATUS_NOT_SUPPORTED;
@@ -1107,26 +1117,130 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
return (ret < 0) ? STATUS_INVALID_SIGNATURE : STATUS_SUCCESS;
}
+static unsigned int get_signature_length( enum alg_id id )
+{
+ switch (id)
+ {
+ case ALG_ID_ECDSA_P256: return 64;
+ case ALG_ID_ECDSA_P384: return 96;
+ default:
+ FIXME( "unhandled algorithm %u\n", id );
+ return 0;
+ }
+}
+
+NTSTATUS format_gnutls_signature( enum alg_id type, gnutls_datum_t signature, UCHAR *output,
+ ULONG output_len, ULONG *ret_len )
+{
+ switch (type)
+ {
+ case ALG_ID_RSA:
+ case ALG_ID_RSA_SIGN:
+ {
+ if (output_len < signature.size) return STATUS_BUFFER_TOO_SMALL;
+ memcpy( output, signature.data, signature.size );
+ *ret_len = signature.size;
+ return STATUS_SUCCESS;
+ }
+ case ALG_ID_ECDSA_P256:
+ case ALG_ID_ECDSA_P384:
+ {
+ int err;
+ unsigned int pad_size, sig_len = get_signature_length( type );
+ gnutls_datum_t r, s; /* format as r||s */
+
+ if ((err = pgnutls_decode_rs_value( &signature, &r, &s )))
+ {
+ ERR( "failed to get R/S values from signature %u\n", err );
+ return 0;
+ }
+
+ if (output_len < sig_len) return STATUS_BUFFER_TOO_SMALL;
+
+ /* remove prepended zero byte */
+ if (r.size % 2)
+ {
+ r.size--;
+ r.data += 1;
+ }
+ if (s.size % 2)
+ {
+ s.size--;
+ s.data += 1;
+ }
+
+ if (r.size != s.size || r.size + s.size > sig_len)
+ {
+ ERR( "we didn't get a correct signature\n" );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ pad_size = (sig_len / 2) - s.size;
+ memset( output, 0, sig_len );
+
+ memcpy( output + pad_size, r.data, r.size );
+ memcpy( output + (sig_len / 2) + pad_size, s.data, s.size );
+
+ *ret_len = sig_len;
+ return STATUS_SUCCESS;
+ }
+ default:
+ return STATUS_INTERNAL_ERROR;
+ }
+}
+
NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output,
ULONG output_len, ULONG *ret_len, ULONG flags )
{
BCRYPT_PKCS1_PADDING_INFO *pad = padding;
gnutls_datum_t hash, signature;
+ gnutls_digest_algorithm_t hash_alg;
+ NTSTATUS status;
int ret;
- if (key->alg_id != ALG_ID_RSA && key->alg_id != ALG_ID_RSA_SIGN)
+ if (key->alg_id == ALG_ID_ECDSA_P256 || key->alg_id == ALG_ID_ECDSA_P384)
{
- FIXME( "algorithm %u not supported\n", key->alg_id );
- return STATUS_NOT_IMPLEMENTED;
+ /* With ECDSA, we find the digest algorithm from the hash length, and verify it */
+ switch (input_len)
+ {
+ case 20: hash_alg = GNUTLS_DIG_SHA1; break;
+ case 32: hash_alg = GNUTLS_DIG_SHA256; break;
+ case 48: hash_alg = GNUTLS_DIG_SHA384; break;
+ case 64: hash_alg = GNUTLS_DIG_SHA512; break;
+
+ default:
+ FIXME( "hash size %u not yet supported\n", input_len );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (flags == BCRYPT_PAD_PKCS1 && pad && pad->pszAlgId && get_digest_from_id( pad->pszAlgId ) != hash_alg)
+ {
+ WARN( "incorrect hashing algorithm %s, expected %u\n", debugstr_w(pad->pszAlgId), hash_alg );
+ return STATUS_INVALID_PARAMETER;
+ }
}
- if (flags != BCRYPT_PAD_PKCS1)
+ else if (flags == BCRYPT_PAD_PKCS1)
{
- FIXME( "flags %08x not implemented\n", flags );
- return STATUS_NOT_IMPLEMENTED;
+ if (!pad || !pad->pszAlgId)
+ {
+ WARN( "padding info not found\n" );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hash_alg = get_digest_from_id( pad->pszAlgId )) == -1)
+ {
+ FIXME( "hash algorithm %s not recognized\n", debugstr_w(pad->pszAlgId) );
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+ else if (!flags)
+ {
+ WARN( "invalid flags %08x\n", flags );
+ return STATUS_INVALID_PARAMETER;
}
- if (!pad || !pad->pszAlgId || lstrcmpiW(pad->pszAlgId, BCRYPT_SHA1_ALGORITHM))
+ else
{
- FIXME( "%s padding not implemented\n", debugstr_w(pad ? pad->pszAlgId : NULL) );
+ FIXME( "flags %08x not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED;
}
@@ -1143,17 +1257,16 @@ NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULON
signature.data = NULL;
signature.size = 0;
- if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, GNUTLS_DIG_SHA1, 0, &hash, &signature )))
+ if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, hash_alg, 0, &hash, &signature )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- if (output_len >= signature.size) memcpy( output, signature.data, signature.size );
- *ret_len = signature.size;
+ status = format_gnutls_signature( key->alg_id, signature, output, output_len, ret_len );
free( signature.data );
- return STATUS_SUCCESS;
+ return status;
}
NTSTATUS key_destroy( struct key *key )
--
2.20.1
Dec. 5, 2019
[PATCH] testbot/LogUtils: Fix GetNewLogErrors() when there are no errors.
by Francois Gouget
Don't use $Groups if it is undefined.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
This fixes WineSendLog and thus the patch status and Marvin emails.
testbot/lib/WineTestBot/LogUtils.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testbot/lib/WineTestBot/LogUtils.pm b/testbot/lib/WineTestBot/LogUtils.pm
index 51932965c..32bf0fa61 100644
--- a/testbot/lib/WineTestBot/LogUtils.pm
+++ b/testbot/lib/WineTestBot/LogUtils.pm
@@ -889,7 +889,7 @@ sub GetNewLogErrors($$$)
my ($RefFileName, $Groups, $Errors) = @_;
my (@NewGroups, %NewErrors, %NewIndices);
- return (\@NewGroups, \%NewErrors, \%NewIndices) if (!@$Groups);
+ return (\@NewGroups, \%NewErrors, \%NewIndices) if (!$Groups or !@$Groups);
my ($RefGroups, $RefErrors) = GetLogErrors($RefFileName);
return (undef, undef) if (!$RefGroups);
--
2.20.1
Dec. 5, 2019
[PATCH] testbot/web: Abuse the Status field to show more details about accounts.
by Francois Gouget
This allows quickly identifying accounts that have been approved but
where the user did not pick a password.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/web/WineTestBot.css | 8 ++++++
testbot/web/admin/UsersList.pl | 47 ++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/testbot/web/WineTestBot.css b/testbot/web/WineTestBot.css
index 1456036c0..f58835583 100644
--- a/testbot/web/WineTestBot.css
+++ b/testbot/web/WineTestBot.css
@@ -387,6 +387,14 @@ pre
.boterror { color: #e55600; }
.canceled { color: black; }
+.userrequest { color: #e55600; }
+.userapproved { color: green; }
+.useradmin { color: black; }
+.userdevel { color: black; }
+.usernone { color: red; }
+.userdisabled { color: red; }
+.userdeleted { color: red; }
+
.log-info { background-color: #d9ffcc; }
.log-skip { color: blue; }
.log-todo { color: #d08000; }
diff --git a/testbot/web/admin/UsersList.pl b/testbot/web/admin/UsersList.pl
index f46949d24..279907041 100644
--- a/testbot/web/admin/UsersList.pl
+++ b/testbot/web/admin/UsersList.pl
@@ -25,6 +25,7 @@ package UsersListPage;
use ObjectModel::CGI::CollectionPage;
our @ISA = qw(ObjectModel::CGI::CollectionPage);
+use URI::Escape;
use WineTestBot::CGI::Sessions;
use WineTestBot::Config;
use WineTestBot::Users;
@@ -55,6 +56,52 @@ sub DisplayProperty($$$)
$PropertyName eq "Status" || $PropertyName eq "RealName";
}
+sub GenerateDataCell($$$$$)
+{
+ my ($self, $CollectionBlock, $Item, $PropertyDescriptor, $DetailsPage) = @_;
+
+ my $PropertyName = $PropertyDescriptor->GetName();
+ if ($PropertyName eq "Status")
+ {
+ my $Status = $Item->Status;
+ my ($Class, $Label);
+ if ($Status eq "disabled")
+ {
+ ($Class, $Label) = ('userdisabled', 'disabled');
+ }
+ elsif ($Status eq "deleted")
+ {
+ ($Class, $Label) = ('userdeleted', 'deleted');
+ }
+ elsif ($Item->WaitingForApproval())
+ {
+ ($Class, $Label) = ('userrequest', 'request');
+ }
+ elsif (!$Item->Activated())
+ {
+ ($Class, $Label) = ('userapproved', 'approved');
+ }
+ elsif ($Item->HasRole("admin"))
+ {
+ ($Class, $Label) = ('useradmin', 'admin');
+ }
+ elsif ($Item->HasRole("wine-devel"))
+ {
+ ($Class, $Label) = ('userdevel', 'wine-devel');
+ }
+ else
+ {
+ ($Class, $Label) = ('usernone', 'none');
+ }
+ print "<td><a href='/admin/UserDetails.pl?Key=", uri_escape($Item->GetKey()),
+ "'><span class='$Class'>$Label</span></a></td>";
+ }
+ else
+ {
+ $self->SUPER::GenerateDataCell($CollectionBlock, $Item, $PropertyDescriptor, $DetailsPage);
+ }
+}
+
sub GetActions($$)
{
my ($self, $CollectionBlock) = @_;
--
2.20.1
Dec. 5, 2019
[PATCH] testbot/web: Require filling the captcha on the feedback page.
by Francois Gouget
Spammers (or their bots) have taken to spamming the TestBot's
feedback page. As if that was going to egt them anywhere!
The captcha is only required for users who are not logged
in obviously.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/web/Feedback.pl | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/testbot/web/Feedback.pl b/testbot/web/Feedback.pl
index 36f0a2b06..b43397fda 100644
--- a/testbot/web/Feedback.pl
+++ b/testbot/web/Feedback.pl
@@ -33,16 +33,21 @@ sub _initialize($$$)
{
my ($self, $Request, $RequiredRole) = @_;
+ my $Session = $self->GetCurrentSession();
my @PropertyDescriptors = (
CreateBasicPropertyDescriptor("Name", "Name", !1, !1, "A", 40),
CreateBasicPropertyDescriptor("EMail", "Email", !1, !1, "A", 40),
CreateBasicPropertyDescriptor("Remarks", "Remarks", !1, 1, "textarea", 1024),
);
+ if (!$Session and $RegistrationQ)
+ {
+ $self->GetParam("FeedA", "") if (!defined $self->GetParam("FeedA"));
+ push @PropertyDescriptors, CreateBasicPropertyDescriptor("FeedA", "Please demonstrate you are not a bot by answering this question: $RegistrationQ", !1, 1, "A", 40);
+ }
$self->SUPER::_initialize($Request, $RequiredRole, \@PropertyDescriptors);
- my $Session = $self->GetCurrentSession();
- if (defined($Session))
+ if ($Session)
{
# Provide default values
my $User = $Session->User;
@@ -79,6 +84,17 @@ sub OnSend($)
{
my ($self) = @_;
+ my $Session = $self->GetCurrentSession();
+ if (!$Session and $RegistrationQ)
+ {
+ my $FeedA = $self->GetParam("FeedA");
+ if ($FeedA !~ /$RegistrationARE/)
+ {
+ $self->{ErrMessage} = "Wrong 'captcha' answer. Please try again.";
+ $self->{ErrField} = "Captcha";
+ return !1;
+ }
+ }
if (! $self->Validate)
{
return !1;
--
2.20.1
Dec. 5, 2019
[PATCH 9/9] dwrite: Use IDWriteFactory7 for gdiinterop.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 4 +-
dlls/dwrite/gdiinterop.c | 162 +++++++++++++++++++----------------
dlls/dwrite/main.c | 8 +-
3 files changed, 93 insertions(+), 81 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 871f93b60b..c2aef6b77c 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -269,14 +269,14 @@ extern HRESULT create_fontfacereference(IDWriteFactory7 *factory, IDWriteFontFil
extern HRESULT factory_get_cached_fontface(IDWriteFactory7 *factory, IDWriteFontFile * const *files, UINT32 num_files,
DWRITE_FONT_SIMULATIONS simulations, struct list **cache, REFIID riid, void **obj) DECLSPEC_HIDDEN;
extern void factory_detach_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection3 *collection) DECLSPEC_HIDDEN;
-extern void factory_detach_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1*) DECLSPEC_HIDDEN;
+extern void factory_detach_gdiinterop(IDWriteFactory7 *factory, IDWriteGdiInterop1 *interop) DECLSPEC_HIDDEN;
extern struct fontfacecached *factory_cache_fontface(IDWriteFactory7 *factory, struct list *fontfaces,
IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
extern void get_logfont_from_font(IDWriteFont*,LOGFONTW*) DECLSPEC_HIDDEN;
extern void get_logfont_from_fontface(IDWriteFontFace*,LOGFONTW*) DECLSPEC_HIDDEN;
extern HRESULT get_fontsig_from_font(IDWriteFont*,FONTSIGNATURE*) DECLSPEC_HIDDEN;
extern HRESULT get_fontsig_from_fontface(IDWriteFontFace*,FONTSIGNATURE*) DECLSPEC_HIDDEN;
-extern HRESULT create_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1**) DECLSPEC_HIDDEN;
+extern HRESULT create_gdiinterop(IDWriteFactory7 *factory, IDWriteGdiInterop1 **interop) DECLSPEC_HIDDEN;
extern void fontface_detach_from_cache(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
extern void factory_lock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN;
extern void factory_unlock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c
index 2e4a949286..7e88f7490c 100644
--- a/dlls/dwrite/gdiinterop.c
+++ b/dlls/dwrite/gdiinterop.c
@@ -38,12 +38,13 @@ struct dib_data {
int width;
};
-struct rendertarget {
+struct rendertarget
+{
IDWriteBitmapRenderTarget1 IDWriteBitmapRenderTarget1_iface;
ID2D1SimplifiedGeometrySink ID2D1SimplifiedGeometrySink_iface;
- LONG ref;
+ LONG refcount;
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
DWRITE_TEXT_ANTIALIAS_MODE antialiasmode;
FLOAT ppdip;
DWRITE_MATRIX m;
@@ -52,11 +53,12 @@ struct rendertarget {
struct dib_data dib;
};
-struct gdiinterop {
+struct gdiinterop
+{
IDWriteGdiInterop1 IDWriteGdiInterop1_iface;
IDWriteFontFileLoader IDWriteFontFileLoader_iface;
- LONG ref;
- IDWriteFactory5 *factory;
+ LONG refcount;
+ IDWriteFactory7 *factory;
};
struct memresource_stream {
@@ -249,27 +251,29 @@ static HRESULT WINAPI rendertarget_QueryInterface(IDWriteBitmapRenderTarget1 *if
static ULONG WINAPI rendertarget_AddRef(IDWriteBitmapRenderTarget1 *iface)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p)->(%d)\n", This, ref);
- return ref;
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
+ ULONG refcount = InterlockedIncrement(&target->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
}
static ULONG WINAPI rendertarget_Release(IDWriteBitmapRenderTarget1 *iface)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
+ ULONG refcount = InterlockedDecrement(&target->refcount);
- TRACE("(%p)->(%d)\n", This, ref);
+ TRACE("%p, refcount %u.\n", iface, refcount);
- if (!ref)
+ if (!refcount)
{
- IDWriteFactory5_Release(This->factory);
- DeleteDC(This->hdc);
- heap_free(This);
+ IDWriteFactory7_Release(target->factory);
+ DeleteDC(target->hdc);
+ heap_free(target);
}
- return ref;
+ return refcount;
}
static inline DWORD *get_pixel_ptr_32(struct dib_data *dib, int x, int y)
@@ -341,22 +345,22 @@ static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *ifac
DWRITE_GLYPH_RUN const *run, IDWriteRenderingParams *params, COLORREF color,
RECT *bbox_ret)
{
- struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
+ struct rendertarget *target = impl_from_IDWriteBitmapRenderTarget1(iface);
IDWriteGlyphRunAnalysis *analysis;
DWRITE_RENDERING_MODE1 rendermode;
DWRITE_GRID_FIT_MODE gridfitmode;
DWRITE_TEXTURE_TYPE texturetype;
DWRITE_GLYPH_RUN scaled_run;
IDWriteFontFace3 *fontface;
- RECT target, bounds;
+ RECT target_rect, bounds;
HRESULT hr;
- TRACE("(%p)->(%.2f %.2f %d %p %p 0x%08x %p)\n", This, originX, originY,
+ TRACE("%p, %.8e, %.8e, %d, %p, %p, 0x%08x, %p.\n", iface, originX, originY,
measuring_mode, run, params, color, bbox_ret);
SetRectEmpty(bbox_ret);
- if (!This->dib.ptr)
+ if (!target->dib.ptr)
return S_OK;
if (!params)
@@ -367,18 +371,19 @@ static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *ifac
return hr;
}
- hr = IDWriteFontFace3_GetRecommendedRenderingMode(fontface, run->fontEmSize, This->ppdip * 96.0f,
- This->ppdip * 96.0f, NULL /* FIXME */, run->isSideways, DWRITE_OUTLINE_THRESHOLD_ALIASED, measuring_mode,
+ hr = IDWriteFontFace3_GetRecommendedRenderingMode(fontface, run->fontEmSize, target->ppdip * 96.0f,
+ target->ppdip * 96.0f, NULL /* FIXME */, run->isSideways, DWRITE_OUTLINE_THRESHOLD_ALIASED, measuring_mode,
params, &rendermode, &gridfitmode);
IDWriteFontFace3_Release(fontface);
if (FAILED(hr))
return hr;
- SetRect(&target, 0, 0, This->size.cx, This->size.cy);
+ SetRect(&target_rect, 0, 0, target->size.cx, target->size.cy);
- if (rendermode == DWRITE_RENDERING_MODE1_OUTLINE) {
+ if (rendermode == DWRITE_RENDERING_MODE1_OUTLINE)
+ {
static const XFORM identity = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
- const DWRITE_MATRIX *m = &This->m;
+ const DWRITE_MATRIX *m = &target->m;
XFORM xform;
/* target allows any transform to be set, filter it here */
@@ -397,40 +402,42 @@ static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *ifac
xform.eDx = m->m11 * originX + m->m21 * originY + m->dx;
xform.eDy = m->m12 * originX + m->m22 * originY + m->dy;
}
- SetWorldTransform(This->hdc, &xform);
+ SetWorldTransform(target->hdc, &xform);
- BeginPath(This->hdc);
+ BeginPath(target->hdc);
- hr = IDWriteFontFace_GetGlyphRunOutline(run->fontFace, run->fontEmSize * This->ppdip,
+ hr = IDWriteFontFace_GetGlyphRunOutline(run->fontFace, run->fontEmSize * target->ppdip,
run->glyphIndices, run->glyphAdvances, run->glyphOffsets, run->glyphCount,
- run->isSideways, run->bidiLevel & 1, &This->ID2D1SimplifiedGeometrySink_iface);
+ run->isSideways, run->bidiLevel & 1, &target->ID2D1SimplifiedGeometrySink_iface);
- EndPath(This->hdc);
+ EndPath(target->hdc);
- if (hr == S_OK) {
+ if (hr == S_OK)
+ {
HBRUSH brush = CreateSolidBrush(color);
- SelectObject(This->hdc, brush);
+ SelectObject(target->hdc, brush);
- FillPath(This->hdc);
+ FillPath(target->hdc);
/* FIXME: one way to get affected rectangle bounds is to use region fill */
if (bbox_ret)
- *bbox_ret = target;
+ *bbox_ret = target_rect;
DeleteObject(brush);
}
- SetWorldTransform(This->hdc, &identity);
+ SetWorldTransform(target->hdc, &identity);
return hr;
}
scaled_run = *run;
- scaled_run.fontEmSize *= This->ppdip;
- hr = IDWriteFactory5_CreateGlyphRunAnalysis(This->factory, &scaled_run, &This->m, rendermode, measuring_mode,
- gridfitmode, This->antialiasmode, originX, originY, &analysis);
- if (FAILED(hr)) {
+ scaled_run.fontEmSize *= target->ppdip;
+ hr = IDWriteFactory7_CreateGlyphRunAnalysis(target->factory, &scaled_run, &target->m, rendermode, measuring_mode,
+ gridfitmode, target->antialiasmode, originX, originY, &analysis);
+ if (FAILED(hr))
+ {
WARN("failed to create analysis instance, 0x%08x\n", hr);
return hr;
}
@@ -448,8 +455,9 @@ static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *ifac
texturetype = DWRITE_TEXTURE_CLEARTYPE_3x1;
}
- if (IntersectRect(&target, &target, &bounds)) {
- UINT32 size = (target.right - target.left) * (target.bottom - target.top);
+ if (IntersectRect(&target_rect, &target_rect, &bounds))
+ {
+ UINT32 size = (target_rect.right - target_rect.left) * (target_rect.bottom - target_rect.top);
BYTE *bitmap;
color = colorref_to_pixel_888(color);
@@ -461,15 +469,15 @@ static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *ifac
return E_OUTOFMEMORY;
}
- hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, texturetype, &target, bitmap, size);
+ hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis, texturetype, &target_rect, bitmap, size);
if (hr == S_OK) {
/* blit to target dib */
if (texturetype == DWRITE_TEXTURE_ALIASED_1x1)
- blit_8(&This->dib, bitmap, &target, color);
+ blit_8(&target->dib, bitmap, &target_rect, color);
else
- blit_subpixel_888(&This->dib, This->size.cx, bitmap, &target, color);
+ blit_subpixel_888(&target->dib, target->size.cx, bitmap, &target_rect, color);
- if (bbox_ret) *bbox_ret = target;
+ if (bbox_ret) *bbox_ret = target_rect;
}
heap_free(bitmap);
@@ -584,7 +592,7 @@ static const IDWriteBitmapRenderTarget1Vtbl rendertargetvtbl = {
rendertarget_SetTextAntialiasMode
};
-static HRESULT create_rendertarget(IDWriteFactory5 *factory, HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **ret)
+static HRESULT create_rendertarget(IDWriteFactory7 *factory, HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **ret)
{
struct rendertarget *target;
HRESULT hr;
@@ -596,7 +604,7 @@ static HRESULT create_rendertarget(IDWriteFactory5 *factory, HDC hdc, UINT32 wid
target->IDWriteBitmapRenderTarget1_iface.lpVtbl = &rendertargetvtbl;
target->ID2D1SimplifiedGeometrySink_iface.lpVtbl = &rendertargetsinkvtbl;
- target->ref = 1;
+ target->refcount = 1;
target->hdc = CreateCompatibleDC(hdc);
SetGraphicsMode(target->hdc, GM_ADVANCED);
@@ -610,7 +618,7 @@ static HRESULT create_rendertarget(IDWriteFactory5 *factory, HDC hdc, UINT32 wid
target->ppdip = GetDeviceCaps(target->hdc, LOGPIXELSX) / 96.0f;
target->antialiasmode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
target->factory = factory;
- IDWriteFactory5_AddRef(factory);
+ IDWriteFactory7_AddRef(factory);
*ret = (IDWriteBitmapRenderTarget*)&target->IDWriteBitmapRenderTarget1_iface;
@@ -640,26 +648,29 @@ static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop1 *iface, REFII
static ULONG WINAPI gdiinterop_AddRef(IDWriteGdiInterop1 *iface)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
- LONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p)->(%d)\n", This, ref);
- return ref;
+ struct gdiinterop *interop = impl_from_IDWriteGdiInterop1(iface);
+ LONG refcount = InterlockedIncrement(&interop->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
}
static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop1 *iface)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
- LONG ref = InterlockedDecrement(&This->ref);
+ struct gdiinterop *interop = impl_from_IDWriteGdiInterop1(iface);
+ LONG refcount = InterlockedDecrement(&interop->refcount);
- TRACE("(%p)->(%d)\n", This, ref);
+ TRACE("%p, refcount %u.\n", iface, refcount);
- if (!ref) {
- IDWriteFactory5_UnregisterFontFileLoader(This->factory, &This->IDWriteFontFileLoader_iface);
- factory_detach_gdiinterop(This->factory, iface);
- heap_free(This);
+ if (!refcount)
+ {
+ IDWriteFactory7_UnregisterFontFileLoader(interop->factory, &interop->IDWriteFontFileLoader_iface);
+ factory_detach_gdiinterop(interop->factory, iface);
+ heap_free(interop);
}
- return ref;
+ return refcount;
}
static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop1 *iface,
@@ -751,7 +762,7 @@ extern BOOL WINAPI GetFontFileData(DWORD instance_id, DWORD unknown, UINT64 offs
static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop1 *iface,
HDC hdc, IDWriteFontFace **fontface)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
+ struct gdiinterop *interop = impl_from_IDWriteGdiInterop1(iface);
struct font_realization_info info;
struct font_fileinfo *fileinfo;
DWRITE_FONT_FILE_TYPE filetype;
@@ -762,7 +773,7 @@ static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop1 *iface
SIZE_T needed;
HRESULT hr;
- TRACE("(%p)->(%p %p)\n", This, hdc, fontface);
+ TRACE("%p, %p, %p.\n", iface, hdc, fontface);
*fontface = NULL;
@@ -793,10 +804,10 @@ static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop1 *iface
}
if (*fileinfo->path)
- hr = IDWriteFactory5_CreateFontFileReference(This->factory, fileinfo->path, &fileinfo->writetime, &file);
+ hr = IDWriteFactory7_CreateFontFileReference(interop->factory, fileinfo->path, &fileinfo->writetime, &file);
else
- hr = IDWriteFactory5_CreateCustomFontFileReference(This->factory, &info.instance_id, sizeof(info.instance_id),
- &This->IDWriteFontFileLoader_iface, &file);
+ hr = IDWriteFactory7_CreateCustomFontFileReference(interop->factory, &info.instance_id,
+ sizeof(info.instance_id), &interop->IDWriteFontFileLoader_iface, &file);
heap_free(fileinfo);
if (FAILED(hr))
@@ -807,7 +818,7 @@ static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop1 *iface
if (SUCCEEDED(hr)) {
if (is_supported)
/* Simulations flags values match DWRITE_FONT_SIMULATIONS */
- hr = IDWriteFactory5_CreateFontFace(This->factory, facetype, 1, &file, info.face_index,
+ hr = IDWriteFactory7_CreateFontFace(interop->factory, facetype, 1, &file, info.face_index,
info.simulations, fontface);
else
hr = DWRITE_E_FILEFORMAT;
@@ -828,14 +839,14 @@ static HRESULT WINAPI gdiinterop_CreateBitmapRenderTarget(IDWriteGdiInterop1 *if
static HRESULT WINAPI gdiinterop1_CreateFontFromLOGFONT(IDWriteGdiInterop1 *iface,
LOGFONTW const *logfont, IDWriteFontCollection *collection, IDWriteFont **font)
{
- struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
+ struct gdiinterop *interop = impl_from_IDWriteGdiInterop1(iface);
IDWriteFontFamily *family;
DWRITE_FONT_STYLE style;
BOOL exists = FALSE;
UINT32 index;
HRESULT hr;
- TRACE("(%p)->(%p %p %p)\n", This, logfont, collection, font);
+ TRACE("%p, %p, %p, %p.\n", iface, logfont, collection, font);
*font = NULL;
@@ -844,7 +855,7 @@ static HRESULT WINAPI gdiinterop1_CreateFontFromLOGFONT(IDWriteGdiInterop1 *ifac
if (collection)
IDWriteFontCollection_AddRef(collection);
else {
- hr = IDWriteFactory5_GetSystemFontCollection(This->factory, FALSE, (IDWriteFontCollection1**)&collection, FALSE);
+ hr = IDWriteFactory5_GetSystemFontCollection((IDWriteFactory5 *)interop->factory, FALSE, (IDWriteFontCollection1 **)&collection, FALSE);
if (FAILED(hr)) {
ERR("failed to get system font collection: 0x%08x.\n", hr);
return hr;
@@ -1089,7 +1100,7 @@ static const struct IDWriteFontFileLoaderVtbl memresourceloadervtbl = {
memresourceloader_CreateStreamFromKey,
};
-HRESULT create_gdiinterop(IDWriteFactory5 *factory, IDWriteGdiInterop1 **ret)
+HRESULT create_gdiinterop(IDWriteFactory7 *factory, IDWriteGdiInterop1 **ret)
{
struct gdiinterop *interop;
@@ -1100,9 +1111,10 @@ HRESULT create_gdiinterop(IDWriteFactory5 *factory, IDWriteGdiInterop1 **ret)
interop->IDWriteGdiInterop1_iface.lpVtbl = &gdiinteropvtbl;
interop->IDWriteFontFileLoader_iface.lpVtbl = &memresourceloadervtbl;
- interop->ref = 1;
- IDWriteFactory5_AddRef(interop->factory = factory);
- IDWriteFactory5_RegisterFontFileLoader(factory, &interop->IDWriteFontFileLoader_iface);
+ interop->refcount = 1;
+ interop->factory = factory;
+ IDWriteFactory7_AddRef(interop->factory);
+ IDWriteFactory7_RegisterFontFileLoader(factory, &interop->IDWriteFontFileLoader_iface);
*ret = &interop->IDWriteGdiInterop1_iface;
return S_OK;
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 73dafffd67..9c88ab6871 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1157,7 +1157,7 @@ static HRESULT WINAPI dwritefactory_GetGdiInterop(IDWriteFactory7 *iface, IDWrit
if (factory->gdiinterop)
IDWriteGdiInterop1_AddRef(factory->gdiinterop);
else
- hr = create_gdiinterop((IDWriteFactory5 *)iface, &factory->gdiinterop);
+ hr = create_gdiinterop(iface, &factory->gdiinterop);
*gdi_interop = (IDWriteGdiInterop *)factory->gdiinterop;
@@ -1893,11 +1893,11 @@ void factory_detach_fontcollection(IDWriteFactory7 *iface, IDWriteFontCollection
IDWriteFactory7_Release(iface);
}
-void factory_detach_gdiinterop(IDWriteFactory5 *iface, IDWriteGdiInterop1 *interop)
+void factory_detach_gdiinterop(IDWriteFactory7 *iface, IDWriteGdiInterop1 *interop)
{
- struct dwritefactory *factory = impl_from_IDWriteFactory7((IDWriteFactory7 *)iface);
+ struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
factory->gdiinterop = NULL;
- IDWriteFactory5_Release(iface);
+ IDWriteFactory7_Release(iface);
}
HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **ret)
--
2.24.0
Dec. 5, 2019
[PATCH 8/9] dwrite: Use IDWriteFactory7 for layout internally.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 5 +++--
dlls/dwrite/layout.c | 14 +++++++-------
dlls/dwrite/main.c | 6 +++---
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index ce693239cf..871f93b60b 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -128,7 +128,7 @@ static inline BOOL is_simulation_valid(DWRITE_FONT_SIMULATIONS simulations)
struct textlayout_desc
{
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
const WCHAR *string;
UINT32 length;
IDWriteTextFormat *format;
@@ -231,7 +231,8 @@ extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const
extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
FLOAT,const WCHAR*,IDWriteTextFormat**) DECLSPEC_HIDDEN;
extern HRESULT create_textlayout(const struct textlayout_desc*,IDWriteTextLayout**) DECLSPEC_HIDDEN;
-extern HRESULT create_trimmingsign(IDWriteFactory5*,IDWriteTextFormat*,IDWriteInlineObject**) DECLSPEC_HIDDEN;
+extern HRESULT create_trimmingsign(IDWriteFactory7 *factory, IDWriteTextFormat *format,
+ IDWriteInlineObject **sign) DECLSPEC_HIDDEN;
extern HRESULT create_typography(IDWriteTypography**) DECLSPEC_HIDDEN;
extern HRESULT create_localizedstrings(IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
extern HRESULT add_localizedstring(IDWriteLocalizedStrings*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 6f166b03f7..b9321157a9 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -251,7 +251,7 @@ struct dwrite_textlayout
IDWriteTextAnalysisSource1 IDWriteTextAnalysisSource1_iface;
LONG refcount;
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
WCHAR *str;
UINT32 len;
@@ -806,7 +806,7 @@ static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
struct layout_run *r;
HRESULT hr;
- if (FAILED(hr = IDWriteFactory5_GetSystemFontCollection(layout->factory, FALSE,
+ if (FAILED(hr = IDWriteFactory5_GetSystemFontCollection((IDWriteFactory5 *)layout->factory, FALSE,
(IDWriteFontCollection1 **)&sys_collection, FALSE))) {
WARN("Failed to get system collection, hr %#x.\n", hr);
return hr;
@@ -817,7 +817,7 @@ static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
IDWriteFontFallback_AddRef(fallback);
}
else {
- if (FAILED(hr = IDWriteFactory5_GetSystemFontFallback(layout->factory, &fallback))) {
+ if (FAILED(hr = IDWriteFactory7_GetSystemFontFallback(layout->factory, &fallback))) {
WARN("Failed to get system fallback, hr %#x.\n", hr);
goto fatal;
}
@@ -2843,7 +2843,7 @@ static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout4 *iface)
if (!refcount)
{
- IDWriteFactory5_Release(layout->factory);
+ IDWriteFactory7_Release(layout->factory);
free_layout_ranges_list(layout);
free_layout_eruns(layout);
free_layout_runs(layout);
@@ -5204,7 +5204,7 @@ static HRESULT init_textlayout(const struct textlayout_desc *desc, struct dwrite
layout->transform = desc->transform ? *desc->transform : identity;
layout->factory = desc->factory;
- IDWriteFactory5_AddRef(layout->factory);
+ IDWriteFactory7_AddRef(layout->factory);
list_add_head(&layout->ranges, &range->entry);
list_add_head(&layout->strike_ranges, &strike->entry);
list_add_head(&layout->underline_ranges, &underline->entry);
@@ -5366,7 +5366,7 @@ static inline BOOL is_flow_direction_vert(DWRITE_FLOW_DIRECTION direction)
(direction == DWRITE_FLOW_DIRECTION_BOTTOM_TO_TOP);
}
-HRESULT create_trimmingsign(IDWriteFactory5 *factory, IDWriteTextFormat *format, IDWriteInlineObject **sign)
+HRESULT create_trimmingsign(IDWriteFactory7 *factory, IDWriteTextFormat *format, IDWriteInlineObject **sign)
{
static const WCHAR ellipsisW = 0x2026;
struct dwrite_trimmingsign *This;
@@ -5392,7 +5392,7 @@ HRESULT create_trimmingsign(IDWriteFactory5 *factory, IDWriteTextFormat *format,
This->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
This->ref = 1;
- hr = IDWriteFactory5_CreateTextLayout(factory, &ellipsisW, 1, format, 0.0f, 0.0f, &This->layout);
+ hr = IDWriteFactory7_CreateTextLayout(factory, &ellipsisW, 1, format, 0.0f, 0.0f, &This->layout);
if (FAILED(hr)) {
heap_free(This);
return hr;
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 448e94058b..73dafffd67 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1171,7 +1171,7 @@ static HRESULT WINAPI dwritefactory_CreateTextLayout(IDWriteFactory7 *iface, WCH
TRACE("%p, %s:%u, %p, %.8e, %.8e, %p.\n", iface, debugstr_wn(string, length), length, format, max_width, max_height, layout);
- desc.factory = (IDWriteFactory5 *)iface;
+ desc.factory = iface;
desc.string = string;
desc.length = length;
desc.format = format;
@@ -1193,7 +1193,7 @@ static HRESULT WINAPI dwritefactory_CreateGdiCompatibleTextLayout(IDWriteFactory
TRACE("%p, %s:%u, %p, %.8e, %.8e, %.8e, %p, %d, %p.\n", iface, debugstr_wn(string, length), length, format,
max_width, max_height, pixels_per_dip, transform, use_gdi_natural, layout);
- desc.factory = (IDWriteFactory5 *)iface;
+ desc.factory = iface;
desc.string = string;
desc.length = length;
desc.format = format;
@@ -1211,7 +1211,7 @@ static HRESULT WINAPI dwritefactory_CreateEllipsisTrimmingSign(IDWriteFactory7 *
{
TRACE("%p, %p, %p.\n", iface, format, trimming_sign);
- return create_trimmingsign((IDWriteFactory5 *)iface, format, trimming_sign);
+ return create_trimmingsign(iface, format, trimming_sign);
}
static HRESULT WINAPI dwritefactory_CreateTextAnalyzer(IDWriteFactory7 *iface, IDWriteTextAnalyzer **analyzer)
--
2.24.0
Dec. 5, 2019
[PATCH 7/9] dwrite: Use IDWriteFactory7 for collections internally.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 12 +++++-----
dlls/dwrite/font.c | 44 +++++++++++++++++++-----------------
dlls/dwrite/main.c | 18 +++++++--------
3 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index ae9576d010..ce693239cf 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -238,15 +238,15 @@ extern HRESULT add_localizedstring(IDWriteLocalizedStrings*,const WCHAR*,const W
extern HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedStrings **strings) DECLSPEC_HIDDEN;
extern void set_en_localizedstring(IDWriteLocalizedStrings*,const WCHAR*) DECLSPEC_HIDDEN;
extern void sort_localizedstrings(IDWriteLocalizedStrings*) DECLSPEC_HIDDEN;
-extern HRESULT get_system_fontcollection(IDWriteFactory5*,IDWriteFontCollection1**) DECLSPEC_HIDDEN;
-extern HRESULT get_eudc_fontcollection(IDWriteFactory5 *factory, IDWriteFontCollection3 **collection) DECLSPEC_HIDDEN;
+extern HRESULT get_system_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection1 **collection) DECLSPEC_HIDDEN;
+extern HRESULT get_eudc_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection3 **collection) DECLSPEC_HIDDEN;
extern IDWriteTextAnalyzer *get_text_analyzer(void) DECLSPEC_HIDDEN;
extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN;
extern void init_local_fontfile_loader(void) DECLSPEC_HIDDEN;
extern IDWriteFontFileLoader *get_local_fontfile_loader(void) DECLSPEC_HIDDEN;
extern HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_list,
IDWriteFontFace5 **fontface) DECLSPEC_HIDDEN;
-extern HRESULT create_font_collection(IDWriteFactory5 *factory, IDWriteFontFileEnumerator *enumerator, BOOL is_system,
+extern HRESULT create_font_collection(IDWriteFactory7 *factory, IDWriteFontFileEnumerator *enumerator, BOOL is_system,
IDWriteFontCollection3 **collection) DECLSPEC_HIDDEN;
extern HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc*,IDWriteGlyphRunAnalysis**) DECLSPEC_HIDDEN;
extern BOOL is_system_collection(IDWriteFontCollection*) DECLSPEC_HIDDEN;
@@ -265,9 +265,9 @@ extern HRESULT create_matching_font(IDWriteFontCollection*,const WCHAR*,DWRITE_F
extern HRESULT create_fontfacereference(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index,
DWRITE_FONT_SIMULATIONS simulations, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 axis_values_count,
IDWriteFontFaceReference1 **reference) DECLSPEC_HIDDEN;
-extern HRESULT factory_get_cached_fontface(IDWriteFactory5*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,
- struct list**,REFIID,void**) DECLSPEC_HIDDEN;
-extern void factory_detach_fontcollection(IDWriteFactory5 *factory, IDWriteFontCollection3 *collection) DECLSPEC_HIDDEN;
+extern HRESULT factory_get_cached_fontface(IDWriteFactory7 *factory, IDWriteFontFile * const *files, UINT32 num_files,
+ DWRITE_FONT_SIMULATIONS simulations, struct list **cache, REFIID riid, void **obj) DECLSPEC_HIDDEN;
+extern void factory_detach_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection3 *collection) DECLSPEC_HIDDEN;
extern void factory_detach_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1*) DECLSPEC_HIDDEN;
extern struct fontfacecached *factory_cache_fontface(IDWriteFactory7 *factory, struct list *fontfaces,
IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index baf915bd17..ef09f8e2bf 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -119,7 +119,7 @@ struct dwrite_fontcollection
IDWriteFontCollection3 IDWriteFontCollection3_iface;
LONG refcount;
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
struct dwrite_fontfamily_data **family_data;
size_t size;
size_t count;
@@ -1828,12 +1828,12 @@ static BOOL WINAPI dwritefont3_Equals(IDWriteFont3 *iface, IDWriteFont *font)
static HRESULT WINAPI dwritefont3_GetFontFaceReference(IDWriteFont3 *iface, IDWriteFontFaceReference **reference)
{
- struct dwrite_font *This = impl_from_IDWriteFont3(iface);
+ struct dwrite_font *font = impl_from_IDWriteFont3(iface);
- TRACE("(%p)->(%p)\n", This, reference);
+ TRACE("%p, %p.\n", iface, reference);
- return IDWriteFactory5_CreateFontFaceReference_(This->family->collection->factory, This->data->file,
- This->data->face_index, This->data->simulations, reference);
+ return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5 *)font->family->collection->factory,
+ font->data->file, font->data->face_index, font->data->simulations, reference);
}
static BOOL WINAPI dwritefont3_HasCharacter(IDWriteFont3 *iface, UINT32 ch)
@@ -3970,7 +3970,7 @@ static void fontcollection_add_replacements(struct dwrite_fontcollection *collec
RegCloseKey(hkey);
}
-HRESULT create_font_collection(IDWriteFactory5 *factory, IDWriteFontFileEnumerator *enumerator, BOOL is_system,
+HRESULT create_font_collection(IDWriteFactory7 *factory, IDWriteFontFileEnumerator *enumerator, BOOL is_system,
IDWriteFontCollection3 **ret)
{
struct fontfile_enum {
@@ -4126,7 +4126,7 @@ HRESULT create_font_collection(IDWriteFactory5 *factory, IDWriteFontFileEnumerat
fontcollection_add_replacements(collection);
collection->factory = factory;
- IDWriteFactory5_AddRef(factory);
+ IDWriteFactory7_AddRef(factory);
return hr;
}
@@ -4136,7 +4136,7 @@ struct system_fontfile_enumerator
IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface;
LONG ref;
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
HKEY hkey;
int index;
@@ -4175,8 +4175,9 @@ static ULONG WINAPI systemfontfileenumerator_Release(IDWriteFontFileEnumerator *
struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface);
ULONG ref = InterlockedDecrement(&enumerator->ref);
- if (!ref) {
- IDWriteFactory5_Release(enumerator->factory);
+ if (!ref)
+ {
+ IDWriteFactory7_Release(enumerator->factory);
RegCloseKey(enumerator->hkey);
heap_free(enumerator->filename);
heap_free(enumerator);
@@ -4185,7 +4186,7 @@ static ULONG WINAPI systemfontfileenumerator_Release(IDWriteFontFileEnumerator *
return ref;
}
-static HRESULT create_local_file_reference(IDWriteFactory5 *factory, const WCHAR *filename, IDWriteFontFile **file)
+static HRESULT create_local_file_reference(IDWriteFactory7 *factory, const WCHAR *filename, IDWriteFontFile **file)
{
HRESULT hr;
@@ -4198,10 +4199,10 @@ static HRESULT create_local_file_reference(IDWriteFactory5 *factory, const WCHAR
strcatW(fullpathW, fontsW);
strcatW(fullpathW, filename);
- hr = IDWriteFactory5_CreateFontFileReference(factory, fullpathW, NULL, file);
+ hr = IDWriteFactory7_CreateFontFileReference(factory, fullpathW, NULL, file);
}
else
- hr = IDWriteFactory5_CreateFontFileReference(factory, filename, NULL, file);
+ hr = IDWriteFactory7_CreateFontFileReference(factory, filename, NULL, file);
return hr;
}
@@ -4283,7 +4284,7 @@ static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl =
systemfontfileenumerator_GetCurrentFontFile
};
-static HRESULT create_system_fontfile_enumerator(IDWriteFactory5 *factory, IDWriteFontFileEnumerator **ret)
+static HRESULT create_system_fontfile_enumerator(IDWriteFactory7 *factory, IDWriteFontFileEnumerator **ret)
{
struct system_fontfile_enumerator *enumerator;
static const WCHAR fontslistW[] = {
@@ -4309,11 +4310,12 @@ static HRESULT create_system_fontfile_enumerator(IDWriteFactory5 *factory, IDWri
return E_OUTOFMEMORY;
}
- IDWriteFactory5_AddRef(factory);
+ IDWriteFactory7_AddRef(factory);
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, fontslistW, 0, GENERIC_READ, &enumerator->hkey)) {
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, fontslistW, 0, GENERIC_READ, &enumerator->hkey))
+ {
ERR("failed to open fonts list key\n");
- IDWriteFactory5_Release(factory);
+ IDWriteFactory7_Release(factory);
heap_free(enumerator->filename);
heap_free(enumerator);
return E_FAIL;
@@ -4324,7 +4326,7 @@ static HRESULT create_system_fontfile_enumerator(IDWriteFactory5 *factory, IDWri
return S_OK;
}
-HRESULT get_system_fontcollection(IDWriteFactory5 *factory, IDWriteFontCollection1 **collection)
+HRESULT get_system_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection1 **collection)
{
IDWriteFontFileEnumerator *enumerator;
HRESULT hr;
@@ -4341,7 +4343,7 @@ HRESULT get_system_fontcollection(IDWriteFactory5 *factory, IDWriteFontCollectio
return hr;
}
-static HRESULT eudc_collection_add_family(IDWriteFactory5 *factory, struct dwrite_fontcollection *collection,
+static HRESULT eudc_collection_add_family(IDWriteFactory7 *factory, struct dwrite_fontcollection *collection,
const WCHAR *keynameW, const WCHAR *pathW)
{
static const WCHAR defaultfontW[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t','E','U','D','C','F','o','n','t',0};
@@ -4429,7 +4431,7 @@ static HRESULT eudc_collection_add_family(IDWriteFactory5 *factory, struct dwrit
return hr;
}
-HRESULT get_eudc_fontcollection(IDWriteFactory5 *factory, IDWriteFontCollection3 **ret)
+HRESULT get_eudc_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection3 **ret)
{
static const WCHAR eudckeyfmtW[] = {'E','U','D','C','\\','%','u',0};
struct dwrite_fontcollection *collection;
@@ -4457,7 +4459,7 @@ HRESULT get_eudc_fontcollection(IDWriteFactory5 *factory, IDWriteFontCollection3
*ret = &collection->IDWriteFontCollection3_iface;
collection->factory = factory;
- IDWriteFactory5_AddRef(factory);
+ IDWriteFactory7_AddRef(factory);
/* return empty collection if EUDC fonts are not configured */
sprintfW(eudckeypathW, eudckeyfmtW, GetACP());
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index a63af6c488..448e94058b 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -667,7 +667,7 @@ static IDWriteFontCollection1 *factory_get_system_collection(struct dwritefactor
return factory->system_collection;
}
- if (FAILED(hr = get_system_fontcollection((IDWriteFactory5 *)&factory->IDWriteFactory7_iface, &collection)))
+ if (FAILED(hr = get_system_fontcollection(&factory->IDWriteFactory7_iface, &collection)))
{
WARN("Failed to create system font collection, hr %#x.\n", hr);
return NULL;
@@ -757,7 +757,7 @@ static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory7 *
if (FAILED(hr))
return hr;
- hr = create_font_collection((IDWriteFactory5 *)iface, enumerator, FALSE, (IDWriteFontCollection3 **)collection);
+ hr = create_font_collection(iface, enumerator, FALSE, (IDWriteFontCollection3 **)collection);
IDWriteFontFileEnumerator_Release(enumerator);
return hr;
}
@@ -859,10 +859,10 @@ void factory_unlock(IDWriteFactory7 *iface)
LeaveCriticalSection(&factory->cs);
}
-HRESULT factory_get_cached_fontface(IDWriteFactory5 *iface, IDWriteFontFile * const *font_files, UINT32 index,
+HRESULT factory_get_cached_fontface(IDWriteFactory7 *iface, IDWriteFontFile * const *font_files, UINT32 index,
DWRITE_FONT_SIMULATIONS simulations, struct list **cached_list, REFIID riid, void **obj)
{
- struct dwritefactory *factory = impl_from_IDWriteFactory7((IDWriteFactory7 *)iface);
+ struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
struct fontfacecached *cached;
IDWriteFontFileLoader *loader;
struct list *fontfaces;
@@ -1001,7 +1001,7 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory7 *iface, DWRIT
goto failed;
}
- hr = factory_get_cached_fontface((IDWriteFactory5 *)iface, font_files, index, simulations, &fontfaces,
+ hr = factory_get_cached_fontface(iface, font_files, index, simulations, &fontfaces,
&IID_IDWriteFontFace, (void **)fontface);
if (hr != S_FALSE)
goto failed;
@@ -1290,7 +1290,7 @@ static HRESULT WINAPI dwritefactory1_GetEudcFontCollection(IDWriteFactory7 *ifac
else {
IDWriteFontCollection3 *eudc_collection;
- if (FAILED(hr = get_eudc_fontcollection((IDWriteFactory5 *)iface, &eudc_collection)))
+ if (FAILED(hr = get_eudc_fontcollection(iface, &eudc_collection)))
{
*collection = NULL;
WARN("Failed to get EUDC collection, hr %#x.\n", hr);
@@ -1885,12 +1885,12 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP
factory->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": dwritefactory.lock");
}
-void factory_detach_fontcollection(IDWriteFactory5 *iface, IDWriteFontCollection3 *collection)
+void factory_detach_fontcollection(IDWriteFactory7 *iface, IDWriteFontCollection3 *collection)
{
- struct dwritefactory *factory = impl_from_IDWriteFactory7((IDWriteFactory7 *)iface);
+ struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
InterlockedCompareExchangePointer((void **)&factory->system_collection, NULL, collection);
InterlockedCompareExchangePointer((void **)&factory->eudc_collection, NULL, collection);
- IDWriteFactory5_Release(iface);
+ IDWriteFactory7_Release(iface);
}
void factory_detach_gdiinterop(IDWriteFactory5 *iface, IDWriteGdiInterop1 *interop)
--
2.24.0
Dec. 5, 2019
[PATCH 6/9] dwrite: Use IDWriteFactory7 for fontface reference object.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 2 +-
dlls/dwrite/font.c | 12 ++++++------
dlls/dwrite/main.c | 9 +++------
3 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 9447c59663..ae9576d010 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -262,7 +262,7 @@ extern void release_system_fontfallback(IDWriteFontFallback1 *fallback) DECLSPEC
extern HRESULT create_fontfallback_builder(IDWriteFactory5*,IDWriteFontFallbackBuilder**) DECLSPEC_HIDDEN;
extern HRESULT create_matching_font(IDWriteFontCollection*,const WCHAR*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
IDWriteFont**) DECLSPEC_HIDDEN;
-extern HRESULT create_fontfacereference(IDWriteFactory5 *factory, IDWriteFontFile *file, UINT32 face_index,
+extern HRESULT create_fontfacereference(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index,
DWRITE_FONT_SIMULATIONS simulations, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 axis_values_count,
IDWriteFontFaceReference1 **reference) DECLSPEC_HIDDEN;
extern HRESULT factory_get_cached_fontface(IDWriteFactory5*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index c9f1e885d5..baf915bd17 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -233,7 +233,7 @@ struct dwrite_fontfacereference
USHORT simulations;
DWRITE_FONT_AXIS_VALUE *axis_values;
UINT32 axis_values_count;
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
};
struct dwrite_fontresource
@@ -6082,7 +6082,7 @@ static ULONG WINAPI fontfacereference_Release(IDWriteFontFaceReference1 *iface)
if (!refcount)
{
IDWriteFontFile_Release(reference->file);
- IDWriteFactory5_Release(reference->factory);
+ IDWriteFactory7_Release(reference->factory);
heap_free(reference->axis_values);
heap_free(reference);
}
@@ -6116,7 +6116,7 @@ static HRESULT WINAPI fontfacereference_CreateFontFaceWithSimulations(IDWriteFon
if (FAILED(hr))
return hr;
- hr = IDWriteFactory5_CreateFontFace(reference->factory, face_type, 1, &reference->file, reference->index,
+ hr = IDWriteFactory7_CreateFontFace(reference->factory, face_type, 1, &reference->file, reference->index,
simulations, &fontface);
if (SUCCEEDED(hr))
{
@@ -6182,7 +6182,7 @@ static HRESULT WINAPI fontfacereference_GetFontFile(IDWriteFontFaceReference1 *i
if (FAILED(hr))
return hr;
- hr = IDWriteFactory5_CreateCustomFontFileReference(reference->factory, key, key_size, loader, file);
+ hr = IDWriteFactory7_CreateCustomFontFileReference(reference->factory, key, key_size, loader, file);
IDWriteFontFileLoader_Release(loader);
return hr;
@@ -6295,7 +6295,7 @@ static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl =
fontfacereference1_GetFontAxisValues,
};
-HRESULT create_fontfacereference(IDWriteFactory5 *factory, IDWriteFontFile *file, UINT32 index,
+HRESULT create_fontfacereference(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 index,
DWRITE_FONT_SIMULATIONS simulations, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 axis_values_count,
IDWriteFontFaceReference1 **ret)
{
@@ -6314,7 +6314,7 @@ HRESULT create_fontfacereference(IDWriteFactory5 *factory, IDWriteFontFile *file
object->refcount = 1;
object->factory = factory;
- IDWriteFactory5_AddRef(object->factory);
+ IDWriteFactory7_AddRef(object->factory);
object->file = file;
IDWriteFontFile_AddRef(object->file);
object->index = index;
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 5f30b8e4f4..a63af6c488 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1443,8 +1443,7 @@ static HRESULT WINAPI dwritefactory3_CreateFontFaceReference_(IDWriteFactory7 *i
{
TRACE("%p, %p, %u, %x, %p.\n", iface, file, index, simulations, reference);
- return create_fontfacereference((IDWriteFactory5 *)iface, file, index, simulations, NULL, 0,
- (IDWriteFontFaceReference1 **)reference);
+ return create_fontfacereference(iface, file, index, simulations, NULL, 0, (IDWriteFontFaceReference1 **)reference);
}
static HRESULT WINAPI dwritefactory3_CreateFontFaceReference(IDWriteFactory7 *iface, WCHAR const *path,
@@ -1463,8 +1462,7 @@ static HRESULT WINAPI dwritefactory3_CreateFontFaceReference(IDWriteFactory7 *if
return hr;
}
- hr = create_fontfacereference((IDWriteFactory5 *)iface, file, index, simulations, NULL, 0,
- (IDWriteFontFaceReference1 **)reference);
+ hr = create_fontfacereference(iface, file, index, simulations, NULL, 0, (IDWriteFontFaceReference1 **)reference);
IDWriteFontFile_Release(file);
return hr;
}
@@ -1664,8 +1662,7 @@ static HRESULT WINAPI dwritefactory6_CreateFontFaceReference(IDWriteFactory7 *if
TRACE("%p, %p, %u, %#x, %p, %u, %p.\n", iface, file, face_index, simulations, axis_values, axis_values_count,
reference);
- return create_fontfacereference((IDWriteFactory5 *)iface, file, face_index, simulations, axis_values,
- axis_values_count, reference);
+ return create_fontfacereference(iface, file, face_index, simulations, axis_values, axis_values_count, reference);
}
static HRESULT WINAPI dwritefactory6_CreateFontResource(IDWriteFactory7 *iface, IDWriteFontFile *file,
--
2.24.0
Dec. 5, 2019
[PATCH 5/9] dwrite: Add newer CreateFontFaceReference() variant.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 5 +++--
dlls/dwrite/font.c | 26 +++++++++++++++++++++-----
dlls/dwrite/main.c | 19 ++++++++++++-------
dlls/dwrite/tests/font.c | 25 +++++++++++++++++++------
4 files changed, 55 insertions(+), 20 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 1598bb6aee..9447c59663 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -262,8 +262,9 @@ extern void release_system_fontfallback(IDWriteFontFallback1 *fallback) DECLSPEC
extern HRESULT create_fontfallback_builder(IDWriteFactory5*,IDWriteFontFallbackBuilder**) DECLSPEC_HIDDEN;
extern HRESULT create_matching_font(IDWriteFontCollection*,const WCHAR*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
IDWriteFont**) DECLSPEC_HIDDEN;
-extern HRESULT create_fontfacereference(IDWriteFactory5*,IDWriteFontFile*,UINT32,DWRITE_FONT_SIMULATIONS,
- IDWriteFontFaceReference**) DECLSPEC_HIDDEN;
+extern HRESULT create_fontfacereference(IDWriteFactory5 *factory, IDWriteFontFile *file, UINT32 face_index,
+ DWRITE_FONT_SIMULATIONS simulations, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 axis_values_count,
+ IDWriteFontFaceReference1 **reference) DECLSPEC_HIDDEN;
extern HRESULT factory_get_cached_fontface(IDWriteFactory5*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,
struct list**,REFIID,void**) DECLSPEC_HIDDEN;
extern void factory_detach_fontcollection(IDWriteFactory5 *factory, IDWriteFontCollection3 *collection) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 8045bce870..c9f1e885d5 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -231,6 +231,8 @@ struct dwrite_fontfacereference
IDWriteFontFile *file;
UINT32 index;
USHORT simulations;
+ DWRITE_FONT_AXIS_VALUE *axis_values;
+ UINT32 axis_values_count;
IDWriteFactory5 *factory;
};
@@ -6081,6 +6083,7 @@ static ULONG WINAPI fontfacereference_Release(IDWriteFontFaceReference1 *iface)
{
IDWriteFontFile_Release(reference->file);
IDWriteFactory5_Release(reference->factory);
+ heap_free(reference->axis_values);
heap_free(reference);
}
@@ -6253,9 +6256,11 @@ static HRESULT WINAPI fontfacereference1_CreateFontFace(IDWriteFontFaceReference
static UINT32 WINAPI fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1 *iface)
{
- FIXME("%p.\n", iface);
+ struct dwrite_fontfacereference *reference = impl_from_IDWriteFontFaceReference1(iface);
- return 0;
+ TRACE("%p.\n", iface);
+
+ return reference->axis_values_count;
}
static HRESULT WINAPI fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1 *iface,
@@ -6291,7 +6296,8 @@ static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl =
};
HRESULT create_fontfacereference(IDWriteFactory5 *factory, IDWriteFontFile *file, UINT32 index,
- DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFaceReference **ret)
+ DWRITE_FONT_SIMULATIONS simulations, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 axis_values_count,
+ IDWriteFontFaceReference1 **ret)
{
struct dwrite_fontfacereference *object;
@@ -6300,7 +6306,7 @@ HRESULT create_fontfacereference(IDWriteFactory5 *factory, IDWriteFontFile *file
if (!is_simulation_valid(simulations))
return E_INVALIDARG;
- object = heap_alloc(sizeof(*object));
+ object = heap_alloc_zero(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
@@ -6313,8 +6319,18 @@ HRESULT create_fontfacereference(IDWriteFactory5 *factory, IDWriteFontFile *file
IDWriteFontFile_AddRef(object->file);
object->index = index;
object->simulations = simulations;
+ if (axis_values_count)
+ {
+ if (!(object->axis_values = heap_alloc(axis_values_count * sizeof(*axis_values))))
+ {
+ IDWriteFontFaceReference1_Release(&object->IDWriteFontFaceReference1_iface);
+ return E_OUTOFMEMORY;
+ }
+ memcpy(object->axis_values, axis_values, axis_values_count * sizeof(*axis_values));
+ object->axis_values_count = axis_values_count;
+ }
- *ret = (IDWriteFontFaceReference *)&object->IDWriteFontFaceReference1_iface;
+ *ret = &object->IDWriteFontFaceReference1_iface;
return S_OK;
}
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index e4b76823ff..5f30b8e4f4 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1443,7 +1443,8 @@ static HRESULT WINAPI dwritefactory3_CreateFontFaceReference_(IDWriteFactory7 *i
{
TRACE("%p, %p, %u, %x, %p.\n", iface, file, index, simulations, reference);
- return create_fontfacereference((IDWriteFactory5 *)iface, file, index, simulations, reference);
+ return create_fontfacereference((IDWriteFactory5 *)iface, file, index, simulations, NULL, 0,
+ (IDWriteFontFaceReference1 **)reference);
}
static HRESULT WINAPI dwritefactory3_CreateFontFaceReference(IDWriteFactory7 *iface, WCHAR const *path,
@@ -1455,13 +1456,15 @@ static HRESULT WINAPI dwritefactory3_CreateFontFaceReference(IDWriteFactory7 *if
TRACE("%p, %s, %p, %u, %#x, %p.\n", iface, debugstr_w(path), writetime, index, simulations, reference);
- hr = IDWriteFactory5_CreateFontFileReference((IDWriteFactory5 *)iface, path, writetime, &file);
- if (FAILED(hr)) {
+ hr = IDWriteFactory7_CreateFontFileReference(iface, path, writetime, &file);
+ if (FAILED(hr))
+ {
*reference = NULL;
return hr;
}
- hr = IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5 *)iface, file, index, simulations, reference);
+ hr = create_fontfacereference((IDWriteFactory5 *)iface, file, index, simulations, NULL, 0,
+ (IDWriteFontFaceReference1 **)reference);
IDWriteFontFile_Release(file);
return hr;
}
@@ -1656,11 +1659,13 @@ static HRESULT WINAPI dwritefactory5_UnpackFontFile(IDWriteFactory7 *iface, DWRI
static HRESULT WINAPI dwritefactory6_CreateFontFaceReference(IDWriteFactory7 *iface, IDWriteFontFile *file,
UINT32 face_index, DWRITE_FONT_SIMULATIONS simulations, DWRITE_FONT_AXIS_VALUE const *axis_values,
- UINT32 num_axis, IDWriteFontFaceReference1 **ref)
+ UINT32 axis_values_count, IDWriteFontFaceReference1 **reference)
{
- FIXME("%p, %p, %u, %#x, %p, %u, %p.\n", iface, file, face_index, simulations, axis_values, num_axis, ref);
+ TRACE("%p, %p, %u, %#x, %p, %u, %p.\n", iface, file, face_index, simulations, axis_values, axis_values_count,
+ reference);
- return E_NOTIMPL;
+ return create_fontfacereference((IDWriteFactory5 *)iface, file, face_index, simulations, axis_values,
+ axis_values_count, reference);
}
static HRESULT WINAPI dwritefactory6_CreateFontResource(IDWriteFactory7 *iface, IDWriteFontFile *file,
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 83d6be4449..5ab01465b7 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -9239,6 +9239,7 @@ static void test_font_resource(void)
IDWriteFontFaceReference1 *reference, *reference2;
IDWriteFontResource *resource, *resource2;
IDWriteFontFile *fontfile, *fontfile2;
+ DWRITE_FONT_AXIS_VALUE axis_value;
IDWriteFontFace5 *fontface5;
IDWriteFontFace *fontface;
IDWriteFactory6 *factory;
@@ -9274,22 +9275,34 @@ static void test_font_resource(void)
index = IDWriteFontResource_GetFontFaceIndex(resource);
ok(!index, "Unexpected index %u.\n", index);
+ /* Specify axis value, font has no variations. */
+ axis_value.axisTag = DWRITE_FONT_AXIS_TAG_WEIGHT;
+ axis_value.value = 400.0f;
+ hr = IDWriteFontResource_CreateFontFaceReference(resource, DWRITE_FONT_SIMULATIONS_NONE, &axis_value, 1, &reference);
+ ok(hr == S_OK, "Failed to create reference object, hr %#x.\n", hr);
+
+ count = IDWriteFontFaceReference1_GetFontAxisValueCount(reference);
+ ok(count == 1, "Unexpected axis value count.\n");
+
+ IDWriteFontFaceReference1_Release(reference);
+
+ hr = IDWriteFactory6_CreateFontFaceReference(factory, fontfile, 0, DWRITE_FONT_SIMULATIONS_NONE, &axis_value, 1,
+ &reference);
+ count = IDWriteFontFaceReference1_GetFontAxisValueCount(reference);
+ ok(count == 1, "Unexpected axis value count.\n");
+ IDWriteFontFaceReference1_Release(reference);
+
EXPECT_REF(resource, 1);
hr = IDWriteFontResource_CreateFontFaceReference(resource, DWRITE_FONT_SIMULATIONS_NONE, NULL, 0, &reference);
-todo_wine
ok(hr == S_OK, "Failed to create reference object, hr %#x.\n", hr);
EXPECT_REF(resource, 1);
hr = IDWriteFontResource_CreateFontFaceReference(resource, DWRITE_FONT_SIMULATIONS_NONE, NULL, 0, &reference2);
-todo_wine
ok(hr == S_OK, "Failed to create reference object, hr %#x.\n", hr);
-
-if (SUCCEEDED(hr))
-{
ok(reference != reference2, "Unexpected reference instance.\n");
IDWriteFontFaceReference1_Release(reference2);
IDWriteFontFaceReference1_Release(reference);
-}
+
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace5, (void **)&fontface5);
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
--
2.24.0
Dec. 5, 2019
[PATCH 4/9] dwrite: Implement GetFontResource() for fontface.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/font.c | 6 ++++--
dlls/dwrite/tests/font.c | 13 ++-----------
2 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 8c58d7561a..8045bce870 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -1435,9 +1435,11 @@ static BOOL WINAPI dwritefontface5_HasVariations(IDWriteFontFace5 *iface)
static HRESULT WINAPI dwritefontface5_GetFontResource(IDWriteFontFace5 *iface, IDWriteFontResource **resource)
{
- FIXME("%p, %p: stub\n", iface, resource);
+ struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, resource);
+
+ return IDWriteFactory7_CreateFontResource(fontface->factory, fontface->files[0], fontface->index, resource);
}
static const IDWriteFontFace5Vtbl dwritefontfacevtbl =
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index d06b2f555a..83d6be4449 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -9294,28 +9294,19 @@ if (SUCCEEDED(hr))
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
hr = IDWriteFontFace5_GetFontResource(fontface5, &resource2);
-todo_wine
ok(hr == S_OK, "Failed to get font resource, hr %#x.\n", hr);
-
-if (SUCCEEDED(hr))
-{
ok(resource != resource2, "Unexpected resource instance.\n");
IDWriteFontResource_Release(resource);
-}
+
hr = IDWriteFontFace5_GetFontResource(fontface5, &resource);
-todo_wine
ok(hr == S_OK, "Failed to get font resource, hr %#x.\n", hr);
-
-if (SUCCEEDED(hr))
-{
ok(resource != resource2, "Unexpected resource instance.\n");
EXPECT_REF(resource, 1);
IDWriteFontResource_Release(resource);
IDWriteFontResource_Release(resource2);
-}
+
IDWriteFontFace5_Release(fontface5);
- IDWriteFontResource_Release(resource);
IDWriteFontFile_Release(fontfile);
IDWriteFontFace_Release(fontface);
--
2.24.0
Dec. 5, 2019
[PATCH 3/9] dwrite: Use IDWriteFactory7 internall for fontfaces.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 10 +++++-----
dlls/dwrite/font.c | 11 ++++++-----
dlls/dwrite/main.c | 14 +++++++-------
3 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index a5d946c385..1598bb6aee 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -154,7 +154,7 @@ struct glyphrunanalysis_desc
struct fontface_desc
{
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
DWRITE_FONT_FACE_TYPE face_type;
IDWriteFontFile * const *files;
IDWriteFontFileStream *stream;
@@ -193,7 +193,7 @@ struct dwrite_fontface
UINT32 file_count;
UINT32 index;
- IDWriteFactory5 *factory;
+ IDWriteFactory7 *factory;
struct fontfacecached *cached;
USHORT simulations;
@@ -268,7 +268,7 @@ extern HRESULT factory_get_cached_fontface(IDWriteFactory5*,IDWriteFontFile*cons
struct list**,REFIID,void**) DECLSPEC_HIDDEN;
extern void factory_detach_fontcollection(IDWriteFactory5 *factory, IDWriteFontCollection3 *collection) DECLSPEC_HIDDEN;
extern void factory_detach_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1*) DECLSPEC_HIDDEN;
-extern struct fontfacecached *factory_cache_fontface(IDWriteFactory5 *factory, struct list *fontfaces,
+extern struct fontfacecached *factory_cache_fontface(IDWriteFactory7 *factory, struct list *fontfaces,
IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
extern void get_logfont_from_font(IDWriteFont*,LOGFONTW*) DECLSPEC_HIDDEN;
extern void get_logfont_from_fontface(IDWriteFontFace*,LOGFONTW*) DECLSPEC_HIDDEN;
@@ -276,8 +276,8 @@ extern HRESULT get_fontsig_from_font(IDWriteFont*,FONTSIGNATURE*) DECLSPEC_HIDDE
extern HRESULT get_fontsig_from_fontface(IDWriteFontFace*,FONTSIGNATURE*) DECLSPEC_HIDDEN;
extern HRESULT create_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1**) DECLSPEC_HIDDEN;
extern void fontface_detach_from_cache(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
-extern void factory_lock(IDWriteFactory5*) DECLSPEC_HIDDEN;
-extern void factory_unlock(IDWriteFactory5*) DECLSPEC_HIDDEN;
+extern void factory_lock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN;
+extern void factory_unlock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN;
extern HRESULT create_inmemory_fileloader(IDWriteFontFileLoader**) DECLSPEC_HIDDEN;
extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index,
IDWriteFontResource **resource) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index bfe32d5fd9..8c58d7561a 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -551,7 +551,7 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace5 *iface)
freetype_notify_cacheremove(iface);
- IDWriteFactory5_Release(fontface->factory);
+ IDWriteFactory7_Release(fontface->factory);
heap_free(fontface);
}
@@ -1518,7 +1518,7 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace5
if (FAILED(hr = get_filestream_from_file(data->file, &desc.stream)))
return hr;
- desc.factory = font->family->collection->factory;
+ desc.factory = (IDWriteFactory7 *)font->family->collection->factory;
desc.face_type = data->face_type;
desc.files = &data->file;
desc.files_number = 1;
@@ -4051,7 +4051,7 @@ HRESULT create_font_collection(IDWriteFactory5 *factory, IDWriteFontFileEnumerat
WCHAR familyW[255];
UINT32 index;
- desc.factory = factory;
+ desc.factory = (IDWriteFactory7 *)factory;
desc.face_type = face_type;
desc.files = &file;
desc.stream = stream;
@@ -4394,7 +4394,7 @@ static HRESULT eudc_collection_add_family(IDWriteFactory5 *factory, struct dwrit
struct fontface_desc desc;
/* alloc and init new font data structure */
- desc.factory = factory;
+ desc.factory = (IDWriteFactory7 *)factory;
desc.face_type = face_type;
desc.index = i;
desc.files = &file;
@@ -4660,7 +4660,8 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
fontface->colr.exists = TRUE;
fontface->index = desc->index;
fontface->simulations = desc->simulations;
- IDWriteFactory5_AddRef(fontface->factory = desc->factory);
+ fontface->factory = desc->factory;
+ IDWriteFactory7_AddRef(fontface->factory);
for (i = 0; i < fontface->file_count; i++) {
fontface->files[i] = desc->files[i];
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 1c1fabdb7d..e4b76823ff 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -847,15 +847,15 @@ static HRESULT WINAPI dwritefactory_CreateCustomFontFileReference(IDWriteFactory
return create_font_file(loader, reference_key, key_size, font_file);
}
-void factory_lock(IDWriteFactory5 *iface)
+void factory_lock(IDWriteFactory7 *iface)
{
- struct dwritefactory *factory = impl_from_IDWriteFactory7((IDWriteFactory7 *)iface);
+ struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
EnterCriticalSection(&factory->cs);
}
-void factory_unlock(IDWriteFactory5 *iface)
+void factory_unlock(IDWriteFactory7 *iface)
{
- struct dwritefactory *factory = impl_from_IDWriteFactory7((IDWriteFactory7 *)iface);
+ struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
LeaveCriticalSection(&factory->cs);
}
@@ -935,10 +935,10 @@ HRESULT factory_get_cached_fontface(IDWriteFactory5 *iface, IDWriteFontFile * co
return *obj ? S_OK : S_FALSE;
}
-struct fontfacecached *factory_cache_fontface(IDWriteFactory5 *iface, struct list *fontfaces,
+struct fontfacecached *factory_cache_fontface(IDWriteFactory7 *iface, struct list *fontfaces,
IDWriteFontFace5 *fontface)
{
- struct dwritefactory *factory = impl_from_IDWriteFactory7((IDWriteFactory7 *)iface);
+ struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
struct fontfacecached *cached;
/* new cache entry */
@@ -1006,7 +1006,7 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory7 *iface, DWRIT
if (hr != S_FALSE)
goto failed;
- desc.factory = (IDWriteFactory5 *)iface;
+ desc.factory = iface;
desc.face_type = req_facetype;
desc.files = font_files;
desc.stream = stream;
--
2.24.0
Dec. 5, 2019
[PATCH 2/9] dwrite: Respond to IDWriteFontFace5 queries.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/font.c | 7 ++++---
dlls/dwrite/tests/font.c | 17 ++++++++++-------
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 8788181303..bfe32d5fd9 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -474,7 +474,8 @@ static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace5 *iface, REF
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
- if (IsEqualIID(riid, &IID_IDWriteFontFace4) ||
+ if (IsEqualIID(riid, &IID_IDWriteFontFace5) ||
+ IsEqualIID(riid, &IID_IDWriteFontFace4) ||
IsEqualIID(riid, &IID_IDWriteFontFace3) ||
IsEqualIID(riid, &IID_IDWriteFontFace2) ||
IsEqualIID(riid, &IID_IDWriteFontFace1) ||
@@ -1425,7 +1426,7 @@ static HRESULT WINAPI dwritefontface5_GetFontAxisValues(IDWriteFontFace5 *iface,
return E_NOTIMPL;
}
-static BOOL WINAPI dwritefontface5_HasVariantions(IDWriteFontFace5 *iface)
+static BOOL WINAPI dwritefontface5_HasVariations(IDWriteFontFace5 *iface)
{
FIXME("%p: stub\n", iface);
@@ -1496,7 +1497,7 @@ static const IDWriteFontFace5Vtbl dwritefontfacevtbl =
dwritefontface4_ReleaseGlyphImageData,
dwritefontface5_GetFontAxisValueCount,
dwritefontface5_GetFontAxisValues,
- dwritefontface5_HasVariantions,
+ dwritefontface5_HasVariations,
dwritefontface5_GetFontResource,
};
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index f0266cb751..d06b2f555a 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -9291,25 +9291,28 @@ if (SUCCEEDED(hr))
IDWriteFontFaceReference1_Release(reference);
}
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace5, (void **)&fontface5);
-todo_wine
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
- if (FAILED(hr))
- return;
-
hr = IDWriteFontFace5_GetFontResource(fontface5, &resource2);
+todo_wine
ok(hr == S_OK, "Failed to get font resource, hr %#x.\n", hr);
+
+if (SUCCEEDED(hr))
+{
ok(resource != resource2, "Unexpected resource instance.\n");
IDWriteFontResource_Release(resource);
-
+}
hr = IDWriteFontFace5_GetFontResource(fontface5, &resource);
+todo_wine
ok(hr == S_OK, "Failed to get font resource, hr %#x.\n", hr);
+
+if (SUCCEEDED(hr))
+{
ok(resource != resource2, "Unexpected resource instance.\n");
EXPECT_REF(resource, 1);
-
IDWriteFontResource_Release(resource);
IDWriteFontResource_Release(resource2);
-
+}
IDWriteFontFace5_Release(fontface5);
IDWriteFontResource_Release(resource);
--
2.24.0
Dec. 5, 2019
[PATCH 1/9] dwrite: Add partial implementation for IDWriteFontResource.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 2 +
dlls/dwrite/font.c | 217 +++++++++++++++++++++++++++++++++++
dlls/dwrite/main.c | 4 +-
dlls/dwrite/tests/font.c | 22 ++--
4 files changed, 233 insertions(+), 12 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 7898403dd9..a5d946c385 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -279,6 +279,8 @@ extern void fontface_detach_from_cache(IDWriteFontFace5 *fontface) DECLSPEC_HIDD
extern void factory_lock(IDWriteFactory5*) DECLSPEC_HIDDEN;
extern void factory_unlock(IDWriteFactory5*) DECLSPEC_HIDDEN;
extern HRESULT create_inmemory_fileloader(IDWriteFontFileLoader**) DECLSPEC_HIDDEN;
+extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index,
+ IDWriteFontResource **resource) DECLSPEC_HIDDEN;
struct dwrite_fontface;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 1bf88d6b17..8788181303 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -234,6 +234,16 @@ struct dwrite_fontfacereference
IDWriteFactory5 *factory;
};
+struct dwrite_fontresource
+{
+ IDWriteFontResource IDWriteFontResource_iface;
+ LONG refcount;
+
+ IDWriteFontFile *file;
+ UINT32 face_index;
+ IDWriteFactory7 *factory;
+};
+
static void dwrite_grab_font_table(void *context, UINT32 table, const BYTE **data, UINT32 *size, void **data_context)
{
struct dwrite_fontface *fontface = context;
@@ -325,6 +335,11 @@ static inline struct dwrite_fontfacereference *impl_from_IDWriteFontFaceReferenc
return CONTAINING_RECORD(iface, struct dwrite_fontfacereference, IDWriteFontFaceReference1_iface);
}
+static struct dwrite_fontresource *impl_from_IDWriteFontResource(IDWriteFontResource *iface)
+{
+ return CONTAINING_RECORD(iface, struct dwrite_fontresource, IDWriteFontResource_iface);
+}
+
static HRESULT get_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *metrics)
{
static const DWRITE_GLYPH_METRICS nil;
@@ -6555,3 +6570,205 @@ HRESULT create_inmemory_fileloader(IDWriteFontFileLoader **ret)
return S_OK;
}
+
+static HRESULT WINAPI dwritefontresource_QueryInterface(IDWriteFontResource *iface, REFIID riid, void **obj)
+{
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+ if (IsEqualIID(riid, &IID_IDWriteFontResource) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IDWriteFontResource_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI dwritefontresource_AddRef(IDWriteFontResource *iface)
+{
+ struct dwrite_fontresource *resource = impl_from_IDWriteFontResource(iface);
+ ULONG refcount = InterlockedIncrement(&resource->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI dwritefontresource_Release(IDWriteFontResource *iface)
+{
+ struct dwrite_fontresource *resource = impl_from_IDWriteFontResource(iface);
+ ULONG refcount = InterlockedDecrement(&resource->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ IDWriteFactory7_Release(resource->factory);
+ IDWriteFontFile_Release(resource->file);
+ heap_free(resource);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI dwritefontresource_GetFontFile(IDWriteFontResource *iface, IDWriteFontFile **fontfile)
+{
+ struct dwrite_fontresource *resource = impl_from_IDWriteFontResource(iface);
+
+ TRACE("%p, %p.\n", iface, fontfile);
+
+ *fontfile = resource->file;
+ IDWriteFontFile_AddRef(*fontfile);
+
+ return S_OK;
+}
+
+static UINT32 WINAPI dwritefontresource_GetFontFaceIndex(IDWriteFontResource *iface)
+{
+ struct dwrite_fontresource *resource = impl_from_IDWriteFontResource(iface);
+
+ TRACE("%p.\n", iface);
+
+ return resource->face_index;
+}
+
+static UINT32 WINAPI dwritefontresource_GetFontAxisCount(IDWriteFontResource *iface)
+{
+ FIXME("%p.\n", iface);
+
+ return 0;
+}
+
+static HRESULT WINAPI dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource *iface,
+ DWRITE_FONT_AXIS_VALUE const *values, UINT32 num_values)
+{
+ FIXME("%p, %p, %u.\n", iface, values, num_values);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dwritefontresource_GetFontAxisRanges(IDWriteFontResource *iface,
+ DWRITE_FONT_AXIS_RANGE const *ranges, UINT32 num_ranges)
+{
+ FIXME("%p, %p, %u.\n", iface, ranges, num_ranges);
+
+ return E_NOTIMPL;
+}
+
+static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI dwritefontresource_GetFontAxisAttributes(IDWriteFontResource *iface,
+ UINT32 axis)
+{
+ FIXME("%p, %u.\n", iface, axis);
+
+ return DWRITE_FONT_AXIS_ATTRIBUTES_NONE;
+}
+
+static HRESULT WINAPI dwritefontresource_GetAxisNames(IDWriteFontResource *iface, UINT32 axis,
+ IDWriteLocalizedStrings **names)
+{
+ FIXME("%p, %u, %p.\n", iface, axis, names);
+
+ return E_NOTIMPL;
+}
+
+static UINT32 WINAPI dwritefontresource_GetAxisValueNameCount(IDWriteFontResource *iface, UINT32 axis)
+{
+ FIXME("%p, %u.\n", iface, axis);
+
+ return 0;
+}
+
+static HRESULT WINAPI dwritefontresource_GetAxisValueNames(IDWriteFontResource *iface, UINT32 axis,
+ UINT32 axis_value, DWRITE_FONT_AXIS_RANGE *axis_range, IDWriteLocalizedStrings **names)
+{
+ FIXME("%p, %u, %u, %p, %p.\n", iface, axis, axis_value, axis_range, names);
+
+ return E_NOTIMPL;
+}
+
+static BOOL WINAPI dwritefontresource_HasVariations(IDWriteFontResource *iface)
+{
+ FIXME("%p.\n", iface);
+
+ return FALSE;
+}
+
+static HRESULT WINAPI dwritefontresource_CreateFontFace(IDWriteFontResource *iface,
+ DWRITE_FONT_SIMULATIONS simulations, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 num_values,
+ IDWriteFontFace5 **fontface)
+{
+ struct dwrite_fontresource *resource = impl_from_IDWriteFontResource(iface);
+ IDWriteFontFaceReference1 *reference;
+ HRESULT hr;
+
+ TRACE("%p, %#x, %p, %u, %p.\n", iface, simulations, axis_values, num_values, fontface);
+
+ hr = IDWriteFactory7_CreateFontFaceReference(resource->factory, resource->file, resource->face_index,
+ simulations, axis_values, num_values, &reference);
+ if (SUCCEEDED(hr))
+ {
+ hr = IDWriteFontFaceReference1_CreateFontFace(reference, fontface);
+ IDWriteFontFaceReference1_Release(reference);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI dwritefontresource_CreateFontFaceReference(IDWriteFontResource *iface,
+ DWRITE_FONT_SIMULATIONS simulations, DWRITE_FONT_AXIS_VALUE const *axis_values, UINT32 num_values,
+ IDWriteFontFaceReference1 **reference)
+{
+ struct dwrite_fontresource *resource = impl_from_IDWriteFontResource(iface);
+
+ TRACE("%p, %#x, %p, %u, %p.\n", iface, simulations, axis_values, num_values, reference);
+
+ return IDWriteFactory7_CreateFontFaceReference(resource->factory, resource->file, resource->face_index,
+ simulations, axis_values, num_values, reference);
+}
+
+static const IDWriteFontResourceVtbl fontresourcevtbl =
+{
+ dwritefontresource_QueryInterface,
+ dwritefontresource_AddRef,
+ dwritefontresource_Release,
+ dwritefontresource_GetFontFile,
+ dwritefontresource_GetFontFaceIndex,
+ dwritefontresource_GetFontAxisCount,
+ dwritefontresource_GetDefaultFontAxisValues,
+ dwritefontresource_GetFontAxisRanges,
+ dwritefontresource_GetFontAxisAttributes,
+ dwritefontresource_GetAxisNames,
+ dwritefontresource_GetAxisValueNameCount,
+ dwritefontresource_GetAxisValueNames,
+ dwritefontresource_HasVariations,
+ dwritefontresource_CreateFontFace,
+ dwritefontresource_CreateFontFaceReference,
+};
+
+HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index,
+ IDWriteFontResource **ret)
+{
+ struct dwrite_fontresource *resource;
+
+ *ret = NULL;
+
+ resource = heap_alloc_zero(sizeof(*resource));
+ if (!resource)
+ return E_OUTOFMEMORY;
+
+ resource->IDWriteFontResource_iface.lpVtbl = &fontresourcevtbl;
+ resource->refcount = 1;
+ resource->face_index = face_index;
+ resource->file = file;
+ IDWriteFontFile_AddRef(resource->file);
+ resource->factory = factory;
+ IDWriteFactory7_AddRef(resource->factory);
+
+ *ret = &resource->IDWriteFontResource_iface;
+
+ return S_OK;
+}
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 033a664dcf..1c1fabdb7d 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1666,9 +1666,9 @@ static HRESULT WINAPI dwritefactory6_CreateFontFaceReference(IDWriteFactory7 *if
static HRESULT WINAPI dwritefactory6_CreateFontResource(IDWriteFactory7 *iface, IDWriteFontFile *file,
UINT32 face_index, IDWriteFontResource **resource)
{
- FIXME("%p, %p, %u, %p.\n", iface, file, face_index, resource);
+ TRACE("%p, %p, %u, %p.\n", iface, file, face_index, resource);
- return E_NOTIMPL;
+ return create_font_resource(iface, file, face_index, resource);
}
static HRESULT WINAPI dwritefactory6_GetSystemFontSet(IDWriteFactory7 *iface, BOOL include_downloadable,
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 58f2af6e7a..f0266cb751 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -9259,17 +9259,8 @@ static void test_font_resource(void)
ok(hr == S_OK, "Failed to get file object, hr %#x.\n", hr);
hr = IDWriteFactory6_CreateFontResource(factory, fontfile, 0, &resource);
-todo_wine
ok(hr == S_OK, "Failed to create font resource, hr %#x.\n", hr);
- if (FAILED(hr))
- {
- IDWriteFactory6_Release(factory);
- IDWriteFontFile_Release(fontfile);
- IDWriteFontFace_Release(fontface);
- return;
- }
-
hr = IDWriteFactory6_CreateFontResource(factory, fontfile, 0, &resource2);
ok(hr == S_OK, "Failed to create font resource, hr %#x.\n", hr);
ok(resource != resource2, "Unexpected instance.\n");
@@ -9283,18 +9274,29 @@ todo_wine
index = IDWriteFontResource_GetFontFaceIndex(resource);
ok(!index, "Unexpected index %u.\n", index);
+ EXPECT_REF(resource, 1);
hr = IDWriteFontResource_CreateFontFaceReference(resource, DWRITE_FONT_SIMULATIONS_NONE, NULL, 0, &reference);
+todo_wine
ok(hr == S_OK, "Failed to create reference object, hr %#x.\n", hr);
+ EXPECT_REF(resource, 1);
hr = IDWriteFontResource_CreateFontFaceReference(resource, DWRITE_FONT_SIMULATIONS_NONE, NULL, 0, &reference2);
+todo_wine
ok(hr == S_OK, "Failed to create reference object, hr %#x.\n", hr);
+
+if (SUCCEEDED(hr))
+{
ok(reference != reference2, "Unexpected reference instance.\n");
IDWriteFontFaceReference1_Release(reference2);
IDWriteFontFaceReference1_Release(reference);
-
+}
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace5, (void **)&fontface5);
+todo_wine
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
+ if (FAILED(hr))
+ return;
+
hr = IDWriteFontFace5_GetFontResource(fontface5, &resource2);
ok(hr == S_OK, "Failed to get font resource, hr %#x.\n", hr);
ok(resource != resource2, "Unexpected resource instance.\n");
--
2.24.0
Dec. 5, 2019
mscoree: fix an error in string access
by Rafał Mużyło
mscoree: fix an error in string access
If parsed_config.private_path is an empty string, wine is doing a Bad
Thing. It shouldn't.
Signed-off-by: Rafał Mużyło <galtgendo(a)o2.pl>
Dec. 5, 2019
[PATCH 4/4] strmbase: Get rid of the "vtbl" parameter to strmbase_filter_init().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/qcap/audiorecord.c | 20 +-----------
dlls/qcap/avico.c | 20 +-----------
dlls/qcap/avimux.c | 20 +-----------
dlls/qcap/smartteefilter.c | 20 +-----------
dlls/qcap/vfwcapture.c | 21 +-----------
dlls/qedit/samplegrabber.c | 21 +-----------
dlls/quartz/dsoundrender.c | 12 +++----
dlls/quartz/filesource.c | 21 +-----------
dlls/quartz/tests/videorenderer.c | 21 +-----------
dlls/quartz/tests/vmr7.c | 21 +-----------
dlls/quartz/tests/vmr9.c | 21 +-----------
dlls/strmbase/filter.c | 53 +++++++++++++++++++++----------
dlls/strmbase/renderer.c | 21 +-----------
dlls/strmbase/transform.c | 22 +------------
dlls/winegstreamer/gstdemux.c | 27 +++-------------
dlls/wineqtdecoder/qtsplitter.c | 20 +-----------
include/wine/strmbase.h | 18 +----------
17 files changed, 60 insertions(+), 319 deletions(-)
diff --git a/dlls/qcap/audiorecord.c b/dlls/qcap/audiorecord.c
index 0262bc5bd8f..3c15734e894 100644
--- a/dlls/qcap/audiorecord.c
+++ b/dlls/qcap/audiorecord.c
@@ -49,24 +49,6 @@ static inline AudioRecord *impl_from_IPersistPropertyBag(IPersistPropertyBag *if
return CONTAINING_RECORD(iface, AudioRecord, IPersistPropertyBag_iface);
}
-static const IBaseFilterVtbl AudioRecordVtbl = {
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
static struct strmbase_pin *audio_record_get_pin(struct strmbase_filter *iface, unsigned int index)
{
FIXME("iface %p, index %u, stub!\n", iface, index);
@@ -186,7 +168,7 @@ IUnknown* WINAPI QCAP_createAudioCaptureFilter(IUnknown *outer, HRESULT *phr)
memset(This, 0, sizeof(*This));
This->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
- strmbase_filter_init(&This->filter, &AudioRecordVtbl, outer, &CLSID_AudioRecord, &filter_ops);
+ strmbase_filter_init(&This->filter, outer, &CLSID_AudioRecord, &filter_ops);
*phr = S_OK;
return &This->filter.IUnknown_inner;
diff --git a/dlls/qcap/avico.c b/dlls/qcap/avico.c
index f65f33fe442..9365c437b4f 100644
--- a/dlls/qcap/avico.c
+++ b/dlls/qcap/avico.c
@@ -111,24 +111,6 @@ static HRESULT fill_format_info(AVICompressor *This, VIDEOINFOHEADER *src_videoi
return S_OK;
}
-static const IBaseFilterVtbl AVICompressorVtbl = {
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo,
-};
-
static struct strmbase_pin *avi_compressor_get_pin(struct strmbase_filter *iface, unsigned int index)
{
AVICompressor *filter = impl_from_strmbase_filter(iface);
@@ -576,7 +558,7 @@ IUnknown* WINAPI QCAP_createAVICompressor(IUnknown *outer, HRESULT *phr)
return NULL;
}
- strmbase_filter_init(&compressor->filter, &AVICompressorVtbl, outer, &CLSID_AVICo, &filter_ops);
+ strmbase_filter_init(&compressor->filter, outer, &CLSID_AVICo, &filter_ops);
compressor->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
diff --git a/dlls/qcap/avimux.c b/dlls/qcap/avimux.c
index a7a9ac7ceda..dc28104c80a 100644
--- a/dlls/qcap/avimux.c
+++ b/dlls/qcap/avimux.c
@@ -672,24 +672,6 @@ static const struct strmbase_filter_ops filter_ops =
.filter_cleanup_stream = avi_mux_cleanup_stream,
};
-static const IBaseFilterVtbl AviMuxVtbl = {
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
static inline AviMux* impl_from_IConfigAviMux(IConfigAviMux *iface)
{
return CONTAINING_RECORD(iface, AviMux, IConfigAviMux_iface);
@@ -1964,7 +1946,7 @@ IUnknown * WINAPI QCAP_createAVIMux(IUnknown *outer, HRESULT *phr)
return NULL;
}
- strmbase_filter_init(&avimux->filter, &AviMuxVtbl, outer, &CLSID_AviDest, &filter_ops);
+ strmbase_filter_init(&avimux->filter, outer, &CLSID_AviDest, &filter_ops);
avimux->IConfigAviMux_iface.lpVtbl = &ConfigAviMuxVtbl;
avimux->IConfigInterleaving_iface.lpVtbl = &ConfigInterleavingVtbl;
avimux->IMediaSeeking_iface.lpVtbl = &MediaSeekingVtbl;
diff --git a/dlls/qcap/smartteefilter.c b/dlls/qcap/smartteefilter.c
index f63a43de50c..7762ec1e500 100644
--- a/dlls/qcap/smartteefilter.c
+++ b/dlls/qcap/smartteefilter.c
@@ -51,24 +51,6 @@ static inline SmartTeeFilter *impl_from_strmbase_pin(struct strmbase_pin *pin)
return impl_from_strmbase_filter(pin->filter);
}
-static const IBaseFilterVtbl SmartTeeFilterVtbl = {
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
static struct strmbase_pin *smart_tee_get_pin(struct strmbase_filter *iface, unsigned int index)
{
SmartTeeFilter *filter = impl_from_strmbase_filter(iface);
@@ -417,7 +399,7 @@ IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr)
}
memset(object, 0, sizeof(*object));
- strmbase_filter_init(&object->filter, &SmartTeeFilterVtbl, outer, &CLSID_SmartTee, &filter_ops);
+ strmbase_filter_init(&object->filter, outer, &CLSID_SmartTee, &filter_ops);
strmbase_sink_init(&object->sink, &SmartTeeFilterInputVtbl, &object->filter, inputW, &sink_ops, NULL);
hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER,
&IID_IMemAllocator, (void **)&object->sink.pAllocator);
diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c
index 0f8beb0f495..e7522ea9b36 100644
--- a/dlls/qcap/vfwcapture.c
+++ b/dlls/qcap/vfwcapture.c
@@ -167,25 +167,6 @@ static const struct strmbase_filter_ops filter_ops =
.filter_cleanup_stream = vfw_capture_cleanup_stream,
};
-static const IBaseFilterVtbl VfwCapture_Vtbl =
-{
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
/* AMStreamConfig interface, we only need to implement {G,S}etFormat */
static HRESULT WINAPI AMStreamConfig_QueryInterface(IAMStreamConfig *iface, REFIID iid, void **out)
{
@@ -611,7 +592,7 @@ IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *outer, HRESULT *phr)
return NULL;
}
- strmbase_filter_init(&object->filter, &VfwCapture_Vtbl, outer, &CLSID_VfwCapture, &filter_ops);
+ strmbase_filter_init(&object->filter, outer, &CLSID_VfwCapture, &filter_ops);
object->IAMStreamConfig_iface.lpVtbl = &IAMStreamConfig_VTable;
object->IAMVideoProcAmp_iface.lpVtbl = &IAMVideoProcAmp_VTable;
diff --git a/dlls/qedit/samplegrabber.c b/dlls/qedit/samplegrabber.c
index af05966c140..019af5c35de 100644
--- a/dlls/qedit/samplegrabber.c
+++ b/dlls/qedit/samplegrabber.c
@@ -489,25 +489,6 @@ SampleGrabber_In_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_M
return S_OK;
}
-static const IBaseFilterVtbl IBaseFilter_VTable =
-{
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo,
-};
-
static const ISampleGrabberVtbl ISampleGrabber_VTable =
{
SampleGrabber_ISampleGrabber_QueryInterface,
@@ -714,7 +695,7 @@ HRESULT SampleGrabber_create(IUnknown *outer, void **out)
}
ZeroMemory(obj, sizeof(SG_Impl));
- strmbase_filter_init(&obj->filter, &IBaseFilter_VTable, outer, &CLSID_SampleGrabber, &filter_ops);
+ strmbase_filter_init(&obj->filter, outer, &CLSID_SampleGrabber, &filter_ops);
obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable;
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index a2c7ca94a62..cad210a8762 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -555,7 +555,7 @@ static HRESULT WINAPI Basicaudio_QueryInterface(IBasicAudio *iface,
TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
- return BaseFilterImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
+ return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppvObj);
}
static ULONG WINAPI Basicaudio_AddRef(IBasicAudio *iface) {
@@ -563,7 +563,7 @@ static ULONG WINAPI Basicaudio_AddRef(IBasicAudio *iface) {
TRACE("(%p/%p)->()\n", This, iface);
- return BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
+ return IUnknown_AddRef(This->renderer.filter.outer_unk);
}
static ULONG WINAPI Basicaudio_Release(IBasicAudio *iface) {
@@ -571,7 +571,7 @@ static ULONG WINAPI Basicaudio_Release(IBasicAudio *iface) {
TRACE("(%p/%p)->()\n", This, iface);
- return BaseFilterImpl_Release(&This->renderer.filter.IBaseFilter_iface);
+ return IUnknown_Release(This->renderer.filter.outer_unk);
}
HRESULT WINAPI basic_audio_GetTypeInfoCount(IBasicAudio *iface, UINT *count)
@@ -708,7 +708,7 @@ static HRESULT WINAPI AMDirectSound_QueryInterface(IAMDirectSound *iface,
TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
- return BaseFilterImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj);
+ return IUnknown_QueryInterface(This->renderer.filter.outer_unk, riid, ppvObj);
}
static ULONG WINAPI AMDirectSound_AddRef(IAMDirectSound *iface)
@@ -717,7 +717,7 @@ static ULONG WINAPI AMDirectSound_AddRef(IAMDirectSound *iface)
TRACE("(%p/%p)->()\n", This, iface);
- return BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
+ return IUnknown_AddRef(This->renderer.filter.outer_unk);
}
static ULONG WINAPI AMDirectSound_Release(IAMDirectSound *iface)
@@ -726,7 +726,7 @@ static ULONG WINAPI AMDirectSound_Release(IAMDirectSound *iface)
TRACE("(%p/%p)->()\n", This, iface);
- return BaseFilterImpl_Release(&This->renderer.filter.IBaseFilter_iface);
+ return IUnknown_Release(This->renderer.filter.outer_unk);
}
/*** IAMDirectSound methods ***/
diff --git a/dlls/quartz/filesource.c b/dlls/quartz/filesource.c
index 1c17980f58c..e0d45730aec 100644
--- a/dlls/quartz/filesource.c
+++ b/dlls/quartz/filesource.c
@@ -412,7 +412,7 @@ HRESULT AsyncReader_create(IUnknown *outer, void **out)
if (!pAsyncRead)
return E_OUTOFMEMORY;
- strmbase_filter_init(&pAsyncRead->filter, &AsyncReader_Vtbl, outer, &CLSID_AsyncReader, &filter_ops);
+ strmbase_filter_init(&pAsyncRead->filter, outer, &CLSID_AsyncReader, &filter_ops);
pAsyncRead->IFileSourceFilter_iface.lpVtbl = &FileSource_Vtbl;
@@ -428,25 +428,6 @@ HRESULT AsyncReader_create(IUnknown *outer, void **out)
return S_OK;
}
-static const IBaseFilterVtbl AsyncReader_Vtbl =
-{
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
static HRESULT WINAPI FileSource_QueryInterface(IFileSourceFilter * iface, REFIID riid, LPVOID * ppv)
{
AsyncReader *This = impl_from_IFileSourceFilter(iface);
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c
index d3810598682..6f9e47b9dc4 100644
--- a/dlls/quartz/tests/videorenderer.c
+++ b/dlls/quartz/tests/videorenderer.c
@@ -495,25 +495,6 @@ struct testfilter
struct strmbase_source source;
};
-static const IBaseFilterVtbl testfilter_vtbl =
-{
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo,
-};
-
static inline struct testfilter *impl_from_BaseFilter(struct strmbase_filter *iface)
{
return CONTAINING_RECORD(iface, struct testfilter, filter);
@@ -597,7 +578,7 @@ static const struct strmbase_source_ops testsource_ops =
static void testfilter_init(struct testfilter *filter)
{
static const GUID clsid = {0xabacab};
- strmbase_filter_init(&filter->filter, &testfilter_vtbl, NULL, &clsid, &testfilter_ops);
+ strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops);
strmbase_source_init(&filter->source, &testsource_vtbl, &filter->filter, L"", &testsource_ops);
}
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c
index 01d9ad10fa4..b8fd3f53cef 100644
--- a/dlls/quartz/tests/vmr7.c
+++ b/dlls/quartz/tests/vmr7.c
@@ -855,25 +855,6 @@ struct testfilter
struct strmbase_source source;
};
-static const IBaseFilterVtbl testfilter_vtbl =
-{
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo,
-};
-
static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface)
{
return CONTAINING_RECORD(iface, struct testfilter, filter);
@@ -957,7 +938,7 @@ static const struct strmbase_source_ops testsource_ops =
static void testfilter_init(struct testfilter *filter)
{
static const GUID clsid = {0xabacab};
- strmbase_filter_init(&filter->filter, &testfilter_vtbl, NULL, &clsid, &testfilter_ops);
+ strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops);
strmbase_source_init(&filter->source, &testsource_vtbl, &filter->filter, L"", &testsource_ops);
}
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index 9379fa11e48..18971495753 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -859,25 +859,6 @@ struct testfilter
struct strmbase_source source;
};
-static const IBaseFilterVtbl testfilter_vtbl =
-{
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo,
-};
-
static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface)
{
return CONTAINING_RECORD(iface, struct testfilter, filter);
@@ -961,7 +942,7 @@ static const struct strmbase_source_ops testsource_ops =
static void testfilter_init(struct testfilter *filter)
{
static const GUID clsid = {0xabacab};
- strmbase_filter_init(&filter->filter, &testfilter_vtbl, NULL, &clsid, &testfilter_ops);
+ strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops);
strmbase_source_init(&filter->source, &testsource_vtbl, &filter->filter, L"", &testsource_ops);
}
diff --git a/dlls/strmbase/filter.c b/dlls/strmbase/filter.c
index f90f760a49e..53307884c4d 100644
--- a/dlls/strmbase/filter.c
+++ b/dlls/strmbase/filter.c
@@ -271,25 +271,25 @@ static inline struct strmbase_filter *impl_from_IBaseFilter(IBaseFilter *iface)
return CONTAINING_RECORD(iface, struct strmbase_filter, IBaseFilter_iface);
}
-HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter *iface, REFIID iid, void **out)
+static HRESULT WINAPI filter_QueryInterface(IBaseFilter *iface, REFIID iid, void **out)
{
struct strmbase_filter *filter = impl_from_IBaseFilter(iface);
return IUnknown_QueryInterface(filter->outer_unk, iid, out);
}
-ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter *iface)
+static ULONG WINAPI filter_AddRef(IBaseFilter *iface)
{
struct strmbase_filter *filter = impl_from_IBaseFilter(iface);
return IUnknown_AddRef(filter->outer_unk);
}
-ULONG WINAPI BaseFilterImpl_Release(IBaseFilter *iface)
+static ULONG WINAPI filter_Release(IBaseFilter *iface)
{
struct strmbase_filter *filter = impl_from_IBaseFilter(iface);
return IUnknown_Release(filter->outer_unk);
}
-HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid)
+static HRESULT WINAPI filter_GetClassID(IBaseFilter * iface, CLSID * pClsid)
{
struct strmbase_filter *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->(%p)\n", This, pClsid);
@@ -299,7 +299,7 @@ HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid)
return S_OK;
}
-HRESULT WINAPI BaseFilterImpl_Stop(IBaseFilter *iface)
+static HRESULT WINAPI filter_Stop(IBaseFilter *iface)
{
struct strmbase_filter *filter = impl_from_IBaseFilter(iface);
HRESULT hr = S_OK;
@@ -320,7 +320,7 @@ HRESULT WINAPI BaseFilterImpl_Stop(IBaseFilter *iface)
return hr;
}
-HRESULT WINAPI BaseFilterImpl_Pause(IBaseFilter *iface)
+static HRESULT WINAPI filter_Pause(IBaseFilter *iface)
{
struct strmbase_filter *filter = impl_from_IBaseFilter(iface);
HRESULT hr = S_OK;
@@ -341,7 +341,7 @@ HRESULT WINAPI BaseFilterImpl_Pause(IBaseFilter *iface)
return hr;
}
-HRESULT WINAPI BaseFilterImpl_Run(IBaseFilter *iface, REFERENCE_TIME start)
+static HRESULT WINAPI filter_Run(IBaseFilter *iface, REFERENCE_TIME start)
{
struct strmbase_filter *filter = impl_from_IBaseFilter(iface);
HRESULT hr = S_OK;
@@ -362,7 +362,7 @@ HRESULT WINAPI BaseFilterImpl_Run(IBaseFilter *iface, REFERENCE_TIME start)
return hr;
}
-HRESULT WINAPI BaseFilterImpl_GetState(IBaseFilter *iface, DWORD timeout, FILTER_STATE *state)
+static HRESULT WINAPI filter_GetState(IBaseFilter *iface, DWORD timeout, FILTER_STATE *state)
{
struct strmbase_filter *filter = impl_from_IBaseFilter(iface);
HRESULT hr = S_OK;
@@ -380,7 +380,7 @@ HRESULT WINAPI BaseFilterImpl_GetState(IBaseFilter *iface, DWORD timeout, FILTER
return hr;
}
-HRESULT WINAPI BaseFilterImpl_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
+static HRESULT WINAPI filter_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
{
struct strmbase_filter *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->(%p)\n", This, pClock);
@@ -398,7 +398,7 @@ HRESULT WINAPI BaseFilterImpl_SetSyncSource(IBaseFilter * iface, IReferenceClock
return S_OK;
}
-HRESULT WINAPI BaseFilterImpl_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
+static HRESULT WINAPI filter_GetSyncSource(IBaseFilter *iface, IReferenceClock **ppClock)
{
struct strmbase_filter *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->(%p)\n", This, ppClock);
@@ -414,7 +414,7 @@ HRESULT WINAPI BaseFilterImpl_GetSyncSource(IBaseFilter * iface, IReferenceClock
return S_OK;
}
-HRESULT WINAPI BaseFilterImpl_EnumPins(IBaseFilter *iface, IEnumPins **enum_pins)
+static HRESULT WINAPI filter_EnumPins(IBaseFilter *iface, IEnumPins **enum_pins)
{
struct strmbase_filter *filter = impl_from_IBaseFilter(iface);
@@ -423,7 +423,7 @@ HRESULT WINAPI BaseFilterImpl_EnumPins(IBaseFilter *iface, IEnumPins **enum_pins
return enum_pins_create(filter, enum_pins);
}
-HRESULT WINAPI BaseFilterImpl_FindPin(IBaseFilter *iface, const WCHAR *id, IPin **ret)
+static HRESULT WINAPI filter_FindPin(IBaseFilter *iface, const WCHAR *id, IPin **ret)
{
struct strmbase_filter *This = impl_from_IBaseFilter(iface);
struct strmbase_pin *pin;
@@ -443,7 +443,7 @@ HRESULT WINAPI BaseFilterImpl_FindPin(IBaseFilter *iface, const WCHAR *id, IPin
return VFW_E_NOT_FOUND;
}
-HRESULT WINAPI BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
+static HRESULT WINAPI filter_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *pInfo)
{
struct strmbase_filter *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->(%p)\n", This, pInfo);
@@ -457,7 +457,7 @@ HRESULT WINAPI BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *
return S_OK;
}
-HRESULT WINAPI BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName )
+static HRESULT WINAPI filter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *pGraph, const WCHAR *pName)
{
struct strmbase_filter *This = impl_from_IBaseFilter(iface);
@@ -476,23 +476,42 @@ HRESULT WINAPI BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface, IFilterGraph
return S_OK;
}
-HRESULT WINAPI BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
+static HRESULT WINAPI filter_QueryVendorInfo(IBaseFilter *iface, WCHAR **pVendorInfo)
{
TRACE("(%p)->(%p)\n", iface, pVendorInfo);
return E_NOTIMPL;
}
+static const IBaseFilterVtbl filter_vtbl =
+{
+ filter_QueryInterface,
+ filter_AddRef,
+ filter_Release,
+ filter_GetClassID,
+ filter_Stop,
+ filter_Pause,
+ filter_Run,
+ filter_GetState,
+ filter_SetSyncSource,
+ filter_GetSyncSource,
+ filter_EnumPins,
+ filter_FindPin,
+ filter_QueryFilterInfo,
+ filter_JoinFilterGraph,
+ filter_QueryVendorInfo,
+};
+
VOID WINAPI BaseFilterImpl_IncrementPinVersion(struct strmbase_filter *filter)
{
InterlockedIncrement(&filter->pin_version);
}
-void strmbase_filter_init(struct strmbase_filter *filter, const IBaseFilterVtbl *vtbl, IUnknown *outer,
+void strmbase_filter_init(struct strmbase_filter *filter, IUnknown *outer,
const CLSID *clsid, const struct strmbase_filter_ops *ops)
{
memset(filter, 0, sizeof(*filter));
- filter->IBaseFilter_iface.lpVtbl = vtbl;
+ filter->IBaseFilter_iface.lpVtbl = &filter_vtbl;
filter->IUnknown_inner.lpVtbl = &filter_inner_vtbl;
filter->outer_unk = outer ? outer : &filter->IUnknown_inner;
filter->refcount = 1;
diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c
index cacbb90e591..d592ab034e6 100644
--- a/dlls/strmbase/renderer.c
+++ b/dlls/strmbase/renderer.c
@@ -448,25 +448,6 @@ HRESULT WINAPI BaseRendererImpl_Receive(struct strmbase_renderer *This, IMediaSa
return hr;
}
-static const IBaseFilterVtbl strmbase_renderer_vtbl =
-{
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
HRESULT WINAPI BaseRendererImpl_ClearPendingSample(struct strmbase_renderer *iface)
{
if (iface->pMediaSample)
@@ -483,7 +464,7 @@ HRESULT WINAPI strmbase_renderer_init(struct strmbase_renderer *filter, IUnknown
HRESULT hr;
memset(filter, 0, sizeof(*filter));
- strmbase_filter_init(&filter->filter, &strmbase_renderer_vtbl, outer, clsid, &filter_ops);
+ strmbase_filter_init(&filter->filter, outer, clsid, &filter_ops);
filter->pFuncsTable = ops;
diff --git a/dlls/strmbase/transform.c b/dlls/strmbase/transform.c
index 9e2582a0dbf..5c079d38e76 100644
--- a/dlls/strmbase/transform.c
+++ b/dlls/strmbase/transform.c
@@ -246,26 +246,6 @@ static const struct strmbase_source_ops source_ops =
.pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator,
};
-
-static const IBaseFilterVtbl transform_vtbl =
-{
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
static TransformFilter *impl_from_source_IQualityControl(IQualityControl *iface)
{
return CONTAINING_RECORD(iface, TransformFilter, source_IQualityControl_iface);
@@ -346,7 +326,7 @@ static HRESULT strmbase_transform_init(IUnknown *outer, const CLSID *clsid,
ISeekingPassThru *passthru;
HRESULT hr;
- strmbase_filter_init(&filter->filter, &transform_vtbl, outer, clsid, &filter_ops);
+ strmbase_filter_init(&filter->filter, outer, clsid, &filter_ops);
InitializeCriticalSection(&filter->csReceive);
filter->csReceive.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": TransformFilter.csReceive");
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index e024d271974..78c8e38701a 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -99,7 +99,6 @@ static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
static const IMediaSeekingVtbl GST_Seeking_Vtbl;
static const IPinVtbl GST_OutputPin_Vtbl;
static const IPinVtbl GST_InputPin_Vtbl;
-static const IBaseFilterVtbl GST_Vtbl;
static const IQualityControlVtbl GSTOutPin_QualityControl_Vtbl;
static struct gstdemux_source *create_pin(struct gstdemux *filter, const WCHAR *name);
@@ -1438,7 +1437,7 @@ IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *outer, HRESULT *phr)
return NULL;
}
- strmbase_filter_init(&object->filter, &GST_Vtbl, outer, &CLSID_Gstreamer_Splitter, &filter_ops);
+ strmbase_filter_init(&object->filter, outer, &CLSID_Gstreamer_Splitter, &filter_ops);
object->no_more_pads_event = CreateEventW(NULL, FALSE, FALSE, NULL);
object->sink.dir = PINDIR_INPUT;
@@ -1453,24 +1452,6 @@ IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *outer, HRESULT *phr)
return &object->filter.IUnknown_inner;
}
-static const IBaseFilterVtbl GST_Vtbl = {
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
static struct gstdemux *impl_from_IAMStreamSelect(IAMStreamSelect *iface)
{
return CONTAINING_RECORD(iface, struct gstdemux, IAMStreamSelect_iface);
@@ -2383,7 +2364,7 @@ IUnknown * CALLBACK wave_parser_create(IUnknown *outer, HRESULT *phr)
return NULL;
}
- strmbase_filter_init(&object->filter, &GST_Vtbl, outer, &CLSID_WAVEParser, &filter_ops);
+ strmbase_filter_init(&object->filter, outer, &CLSID_WAVEParser, &filter_ops);
object->sink.dir = PINDIR_INPUT;
object->sink.filter = &object->filter;
@@ -2489,7 +2470,7 @@ IUnknown * CALLBACK avi_splitter_create(IUnknown *outer, HRESULT *phr)
return NULL;
}
- strmbase_filter_init(&object->filter, &GST_Vtbl, outer, &CLSID_AviSplitter, &filter_ops);
+ strmbase_filter_init(&object->filter, outer, &CLSID_AviSplitter, &filter_ops);
object->no_more_pads_event = CreateEventW(NULL, FALSE, FALSE, NULL);
object->sink.dir = PINDIR_INPUT;
@@ -2627,7 +2608,7 @@ IUnknown * CALLBACK mpeg_splitter_create(IUnknown *outer, HRESULT *phr)
return NULL;
}
- strmbase_filter_init(&object->filter, &GST_Vtbl, outer, &CLSID_MPEG1Splitter, &mpeg_splitter_ops);
+ strmbase_filter_init(&object->filter, outer, &CLSID_MPEG1Splitter, &mpeg_splitter_ops);
object->IAMStreamSelect_iface.lpVtbl = &stream_select_vtbl;
object->duration_event = CreateEventW(NULL, FALSE, FALSE, NULL);
diff --git a/dlls/wineqtdecoder/qtsplitter.c b/dlls/wineqtdecoder/qtsplitter.c
index 28ea36785a8..5b1e82ebc9b 100644
--- a/dlls/wineqtdecoder/qtsplitter.c
+++ b/dlls/wineqtdecoder/qtsplitter.c
@@ -357,7 +357,7 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *outer, HRESULT *phr)
}
ZeroMemory(This,sizeof(*This));
- strmbase_filter_init(&This->filter, &QT_Vtbl, outer, &CLSID_QTSplitter, &filter_ops);
+ strmbase_filter_init(&This->filter, outer, &CLSID_QTSplitter, &filter_ops);
InitializeCriticalSection(&This->csReceive);
This->csReceive.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": QTSplitter.csReceive");
@@ -721,24 +721,6 @@ audio_error:
return hr;
}
-static const IBaseFilterVtbl QT_Vtbl = {
- BaseFilterImpl_QueryInterface,
- BaseFilterImpl_AddRef,
- BaseFilterImpl_Release,
- BaseFilterImpl_GetClassID,
- BaseFilterImpl_Stop,
- BaseFilterImpl_Pause,
- BaseFilterImpl_Run,
- BaseFilterImpl_GetState,
- BaseFilterImpl_SetSyncSource,
- BaseFilterImpl_GetSyncSource,
- BaseFilterImpl_EnumPins,
- BaseFilterImpl_FindPin,
- BaseFilterImpl_QueryFilterInfo,
- BaseFilterImpl_JoinFilterGraph,
- BaseFilterImpl_QueryVendorInfo
-};
-
static void free_source_pin(QTOutPin *pin)
{
if (pin->pin.pin.peer)
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index 7949e6670a5..75eac504209 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -176,25 +176,9 @@ struct strmbase_filter_ops
HRESULT (*filter_wait_state)(struct strmbase_filter *iface, DWORD timeout);
};
-HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv);
-ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter * iface);
-ULONG WINAPI BaseFilterImpl_Release(IBaseFilter * iface);
-HRESULT WINAPI BaseFilterImpl_Stop(IBaseFilter *iface);
-HRESULT WINAPI BaseFilterImpl_Pause(IBaseFilter *iface);
-HRESULT WINAPI BaseFilterImpl_Run(IBaseFilter *iface, REFERENCE_TIME start);
-HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid);
-HRESULT WINAPI BaseFilterImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState );
-HRESULT WINAPI BaseFilterImpl_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock);
-HRESULT WINAPI BaseFilterImpl_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock);
-HRESULT WINAPI BaseFilterImpl_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum);
-HRESULT WINAPI BaseFilterImpl_FindPin(IBaseFilter *iface, const WCHAR *id, IPin **pin);
-HRESULT WINAPI BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo);
-HRESULT WINAPI BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName );
-HRESULT WINAPI BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo);
-
VOID WINAPI BaseFilterImpl_IncrementPinVersion(struct strmbase_filter *filter);
-void strmbase_filter_init(struct strmbase_filter *filter, const IBaseFilterVtbl *vtbl, IUnknown *outer,
+void strmbase_filter_init(struct strmbase_filter *filter, IUnknown *outer,
const CLSID *clsid, const struct strmbase_filter_ops *func_table);
void strmbase_filter_cleanup(struct strmbase_filter *filter);
--
2.23.0
Dec. 5, 2019
[PATCH 3/4] qcap: Rework v4l2 state change logic.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/qcap/capture.h | 7 +-
dlls/qcap/v4l.c | 166 +++++++++++++----------------------------
dlls/qcap/vfwcapture.c | 60 ++++++++-------
3 files changed, 89 insertions(+), 144 deletions(-)
diff --git a/dlls/qcap/capture.h b/dlls/qcap/capture.h
index 6433f37d88f..7d2be332488 100644
--- a/dlls/qcap/capture.h
+++ b/dlls/qcap/capture.h
@@ -31,8 +31,9 @@ HRESULT qcap_driver_get_format(const Capture *, AM_MEDIA_TYPE *) DECLSPEC_HIDDEN
HRESULT qcap_driver_get_prop_range(Capture*,VideoProcAmpProperty,LONG*,LONG*,LONG*,LONG*,LONG*) DECLSPEC_HIDDEN;
HRESULT qcap_driver_get_prop(Capture*,VideoProcAmpProperty,LONG*,LONG*) DECLSPEC_HIDDEN;
HRESULT qcap_driver_set_prop(Capture*,VideoProcAmpProperty,LONG,LONG) DECLSPEC_HIDDEN;
-HRESULT qcap_driver_run(Capture*,FILTER_STATE*) DECLSPEC_HIDDEN;
-HRESULT qcap_driver_pause(Capture*,FILTER_STATE*) DECLSPEC_HIDDEN;
-HRESULT qcap_driver_stop(Capture*,FILTER_STATE*) DECLSPEC_HIDDEN;
+void qcap_driver_init_stream(Capture *device) DECLSPEC_HIDDEN;
+void qcap_driver_start_stream(Capture *device) DECLSPEC_HIDDEN;
+void qcap_driver_stop_stream(Capture *device) DECLSPEC_HIDDEN;
+void qcap_driver_cleanup_stream(Capture *device) DECLSPEC_HIDDEN;
#endif /* __QCAP_CAPTURE_H__ */
diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c
index a203e91e52b..75121fd8518 100644
--- a/dlls/qcap/v4l.c
+++ b/dlls/qcap/v4l.c
@@ -99,13 +99,11 @@ struct _Capture
UINT width, height, bitDepth, fps, outputwidth, outputheight;
BOOL swresize;
- CRITICAL_SECTION CritSect;
-
struct strmbase_source *pin;
int fd, mmap;
- BOOL iscommitted, stopped;
+ FILTER_STATE state;
- HANDLE thread;
+ HANDLE thread, run_event;
};
static int xioctl(int fd, int request, void * arg)
@@ -125,8 +123,6 @@ HRESULT qcap_driver_destroy(Capture *capBox)
if( capBox->fd != -1 )
video_close(capBox->fd);
- capBox->CritSect.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&capBox->CritSect);
CoTaskMemFree(capBox);
return S_OK;
}
@@ -389,16 +385,14 @@ static DWORD WINAPI ReadThread(LPVOID lParam)
if (!(image_data = heap_alloc(image_size)))
{
ERR("Failed to allocate memory.\n");
- capBox->thread = 0;
- capBox->stopped = TRUE;
return 0;
}
- while (1)
+ while (capBox->state != State_Stopped)
{
- EnterCriticalSection(&capBox->CritSect);
- if (capBox->stopped)
- break;
+ if (capBox->state == State_Paused)
+ WaitForSingleObject(capBox->run_event, INFINITE);
+
hr = BaseOutputPinImpl_GetDeliveryBuffer(capBox->pin, &pSample, NULL, NULL, 0);
if (SUCCEEDED(hr))
{
@@ -432,124 +426,66 @@ static DWORD WINAPI ReadThread(LPVOID lParam)
if (FAILED(hr) && hr != VFW_E_NOT_CONNECTED)
{
TRACE("Return %x, stop IFilterGraph\n", hr);
- capBox->thread = 0;
- capBox->stopped = TRUE;
break;
}
- LeaveCriticalSection(&capBox->CritSect);
}
- LeaveCriticalSection(&capBox->CritSect);
heap_free(image_data);
return 0;
}
-HRESULT qcap_driver_run(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_init_stream(Capture *device)
{
- HANDLE thread;
+ ALLOCATOR_PROPERTIES req_props, ret_props;
HRESULT hr;
- TRACE("%p -> (%p)\n", capBox, state);
-
- if (*state == State_Running) return S_OK;
-
- EnterCriticalSection(&capBox->CritSect);
+ req_props.cBuffers = 3;
+ if (!device->swresize)
+ req_props.cbBuffer = device->width * device->height;
+ else
+ req_props.cbBuffer = device->outputwidth * device->outputheight;
+ req_props.cbBuffer = (req_props.cbBuffer * device->bitDepth) / 8;
+ req_props.cbAlign = 1;
+ req_props.cbPrefix = 0;
- capBox->stopped = FALSE;
+ hr = IMemAllocator_SetProperties(device->pin->pAllocator, &req_props, &ret_props);
+ if (FAILED(hr))
+ ERR("Failed to set allocator properties (buffer size %u), hr %#x.\n", req_props.cbBuffer, hr);
- if (*state == State_Stopped && capBox->pin->pin.peer)
+ if (SUCCEEDED(hr))
{
- *state = State_Running;
- if (!capBox->iscommitted)
- {
- ALLOCATOR_PROPERTIES ap, actual;
-
- capBox->iscommitted = TRUE;
-
- ap.cBuffers = 3;
- if (!capBox->swresize)
- ap.cbBuffer = capBox->width * capBox->height;
- else
- ap.cbBuffer = capBox->outputwidth * capBox->outputheight;
- ap.cbBuffer = (ap.cbBuffer * capBox->bitDepth) / 8;
- ap.cbAlign = 1;
- ap.cbPrefix = 0;
-
- hr = IMemAllocator_SetProperties(capBox->pin->pAllocator, &ap, &actual);
-
- if (SUCCEEDED(hr))
- hr = IMemAllocator_Commit(capBox->pin->pAllocator);
-
- TRACE("Committing allocator: %x\n", hr);
- }
-
- thread = CreateThread(NULL, 0, ReadThread, capBox, 0, NULL);
- if (thread)
- {
- capBox->thread = thread;
- SetThreadPriority(thread, THREAD_PRIORITY_LOWEST);
- LeaveCriticalSection(&capBox->CritSect);
- return S_OK;
- }
- ERR("Creating thread failed.. %u\n", GetLastError());
- LeaveCriticalSection(&capBox->CritSect);
- return E_FAIL;
+ if (FAILED(hr = IMemAllocator_Commit(device->pin->pAllocator)))
+ ERR("Failed to commit allocator, hr %#x.\n", hr);
}
- ResumeThread(capBox->thread);
- *state = State_Running;
- LeaveCriticalSection(&capBox->CritSect);
- return S_OK;
+ device->state = State_Paused;
+ device->thread = CreateThread(NULL, 0, ReadThread, device, 0, NULL);
}
-HRESULT qcap_driver_pause(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_start_stream(Capture *device)
{
- TRACE("%p -> (%p)\n", capBox, state);
-
- if (*state == State_Paused)
- return S_OK;
- if (*state == State_Stopped)
- qcap_driver_run(capBox, state);
-
- EnterCriticalSection(&capBox->CritSect);
- *state = State_Paused;
- SuspendThread(capBox->thread);
- LeaveCriticalSection(&capBox->CritSect);
-
- return S_OK;
+ device->state = State_Running;
+ SetEvent(device->run_event);
}
-HRESULT qcap_driver_stop(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_stop_stream(Capture *device)
{
- TRACE("%p -> (%p)\n", capBox, state);
-
- if (*state == State_Stopped)
- return S_OK;
-
- EnterCriticalSection(&capBox->CritSect);
-
- if (capBox->thread)
- {
- if (*state == State_Paused)
- ResumeThread(capBox->thread);
- capBox->stopped = TRUE;
- capBox->thread = 0;
- if (capBox->iscommitted)
- {
- HRESULT hr;
-
- capBox->iscommitted = FALSE;
-
- hr = IMemAllocator_Decommit(capBox->pin->pAllocator);
+ device->state = State_Paused;
+ ResetEvent(device->run_event);
+}
- if (hr != S_OK && hr != VFW_E_NOT_COMMITTED)
- WARN("Decommitting allocator: %x\n", hr);
- }
- }
+void qcap_driver_cleanup_stream(Capture *device)
+{
+ HRESULT hr;
- *state = State_Stopped;
- LeaveCriticalSection(&capBox->CritSect);
- return S_OK;
+ device->state = State_Stopped;
+ WaitForSingleObject(device->thread, INFINITE);
+ CloseHandle(device->thread);
+ device->thread = NULL;
+
+ hr = IMemAllocator_Decommit(device->pin->pAllocator);
+ if (hr != S_OK && hr != VFW_E_NOT_COMMITTED)
+ ERR("Failed to decommit allocator, hr %#x.\n", hr);
}
Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
@@ -566,9 +502,6 @@ Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
if (!(device = CoTaskMemAlloc(sizeof(*device))))
return NULL;
- InitializeCriticalSection(&device->CritSect);
- device->CritSect.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": Capture.CritSect");
-
sprintf(path, "/dev/video%i", card);
TRACE("Opening device %s.\n", path);
#ifdef O_CLOEXEC
@@ -635,8 +568,8 @@ Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
device->bitDepth = 24;
device->pin = pin;
device->fps = 3;
- device->stopped = FALSE;
- device->iscommitted = FALSE;
+ device->state = State_Stopped;
+ device->run_event = CreateEventW(NULL, TRUE, FALSE, NULL);
TRACE("Format: %d bpp - %dx%d.\n", device->bitDepth, device->width, device->height);
@@ -701,17 +634,22 @@ HRESULT qcap_driver_set_prop(Capture *capBox, VideoProcAmpProperty Property,
FAIL_WITH_ERR;
}
-HRESULT qcap_driver_run(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_init_stream(Capture *device)
+{
+ FAIL_WITH_ERR;
+}
+
+void qcap_driver_start_stream(Capture *device)
{
FAIL_WITH_ERR;
}
-HRESULT qcap_driver_pause(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_stop_stream(Capture *device)
{
FAIL_WITH_ERR;
}
-HRESULT qcap_driver_stop(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_cleanup_stream(Capture *device)
{
FAIL_WITH_ERR;
}
diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c
index 2b60e542eba..0f8beb0f495 100644
--- a/dlls/qcap/vfwcapture.c
+++ b/dlls/qcap/vfwcapture.c
@@ -62,11 +62,6 @@ static inline VfwCapture *impl_from_strmbase_filter(struct strmbase_filter *ifac
return CONTAINING_RECORD(iface, VfwCapture, filter);
}
-static inline VfwCapture *impl_from_IBaseFilter(IBaseFilter *iface)
-{
- return CONTAINING_RECORD(iface, VfwCapture, filter.IBaseFilter_iface);
-}
-
static inline VfwCapture *impl_from_IAMStreamConfig(IAMStreamConfig *iface)
{
return CONTAINING_RECORD(iface, VfwCapture, IAMStreamConfig_iface);
@@ -99,7 +94,7 @@ static void vfw_capture_destroy(struct strmbase_filter *iface)
if (filter->init)
{
if (filter->filter.state != State_Stopped)
- qcap_driver_stop(filter->driver_info, &filter->filter.state);
+ qcap_driver_stop_stream(filter->driver_info);
qcap_driver_destroy(filter->driver_info);
}
@@ -129,47 +124,58 @@ static HRESULT vfw_capture_query_interface(struct strmbase_filter *iface, REFIID
return S_OK;
}
-static const struct strmbase_filter_ops filter_ops =
+static HRESULT vfw_capture_init_stream(struct strmbase_filter *iface)
{
- .filter_get_pin = vfw_capture_get_pin,
- .filter_destroy = vfw_capture_destroy,
- .filter_query_interface = vfw_capture_query_interface,
-};
+ VfwCapture *filter = impl_from_strmbase_filter(iface);
-/** IMediaFilter methods **/
+ qcap_driver_init_stream(filter->driver_info);
+ return VFW_S_CANT_CUE;
+}
-static HRESULT WINAPI VfwCapture_Stop(IBaseFilter * iface)
+static HRESULT vfw_capture_start_stream(struct strmbase_filter *iface, REFERENCE_TIME time)
{
- VfwCapture *This = impl_from_IBaseFilter(iface);
+ VfwCapture *filter = impl_from_strmbase_filter(iface);
- TRACE("()\n");
- return qcap_driver_stop(This->driver_info, &This->filter.state);
+ qcap_driver_start_stream(filter->driver_info);
+ return S_OK;
}
-static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
+static HRESULT vfw_capture_stop_stream(struct strmbase_filter *iface)
{
- VfwCapture *This = impl_from_IBaseFilter(iface);
+ VfwCapture *filter = impl_from_strmbase_filter(iface);
- TRACE("()\n");
- return qcap_driver_pause(This->driver_info, &This->filter.state);
+ qcap_driver_stop_stream(filter->driver_info);
+ return VFW_S_CANT_CUE;
}
-static HRESULT WINAPI VfwCapture_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+static HRESULT vfw_capture_cleanup_stream(struct strmbase_filter *iface)
{
- VfwCapture *This = impl_from_IBaseFilter(iface);
- TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
- return qcap_driver_run(This->driver_info, &This->filter.state);
+ VfwCapture *filter = impl_from_strmbase_filter(iface);
+
+ qcap_driver_cleanup_stream(filter->driver_info);
+ return S_OK;
}
+static const struct strmbase_filter_ops filter_ops =
+{
+ .filter_get_pin = vfw_capture_get_pin,
+ .filter_destroy = vfw_capture_destroy,
+ .filter_query_interface = vfw_capture_query_interface,
+ .filter_init_stream = vfw_capture_init_stream,
+ .filter_start_stream = vfw_capture_start_stream,
+ .filter_stop_stream = vfw_capture_stop_stream,
+ .filter_cleanup_stream = vfw_capture_cleanup_stream,
+};
+
static const IBaseFilterVtbl VfwCapture_Vtbl =
{
BaseFilterImpl_QueryInterface,
BaseFilterImpl_AddRef,
BaseFilterImpl_Release,
BaseFilterImpl_GetClassID,
- VfwCapture_Stop,
- VfwCapture_Pause,
- VfwCapture_Run,
+ BaseFilterImpl_Stop,
+ BaseFilterImpl_Pause,
+ BaseFilterImpl_Run,
BaseFilterImpl_GetState,
BaseFilterImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
--
2.23.0
Dec. 5, 2019
[PATCH 2/4] qcap/avimux: Use strmbase filter state change methods.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/qcap/avimux.c | 58 +++++++++++++---------------------------------
1 file changed, 16 insertions(+), 42 deletions(-)
diff --git a/dlls/qcap/avimux.c b/dlls/qcap/avimux.c
index 1995358ac2f..a7a9ac7ceda 100644
--- a/dlls/qcap/avimux.c
+++ b/dlls/qcap/avimux.c
@@ -167,19 +167,6 @@ static HRESULT avi_mux_query_interface(struct strmbase_filter *iface, REFIID iid
return S_OK;
}
-static const struct strmbase_filter_ops filter_ops =
-{
- .filter_get_pin = avi_mux_get_pin,
- .filter_destroy = avi_mux_destroy,
- .filter_query_interface = avi_mux_query_interface,
-};
-
-static inline AviMux* impl_from_IBaseFilter(IBaseFilter *iface)
-{
- struct strmbase_filter *filter = CONTAINING_RECORD(iface, struct strmbase_filter, IBaseFilter_iface);
- return impl_from_strmbase_filter(filter);
-}
-
static HRESULT out_flush(AviMux *This)
{
ULONG written;
@@ -420,17 +407,12 @@ static HRESULT queue_sample(AviMux *avimux, AviMuxIn *avimuxin, IMediaSample *sa
return flush_queue(avimux, avimuxin, FALSE);
}
-static HRESULT WINAPI AviMux_Stop(IBaseFilter *iface)
+static HRESULT avi_mux_cleanup_stream(struct strmbase_filter *iface)
{
- AviMux *This = impl_from_IBaseFilter(iface);
+ AviMux *This = impl_from_strmbase_filter(iface);
HRESULT hr;
int i;
- TRACE("(%p)\n", This);
-
- if(This->filter.state == State_Stopped)
- return S_OK;
-
if (This->stream)
{
AVIEXTHEADER dmlh;
@@ -559,36 +541,20 @@ static HRESULT WINAPI AviMux_Stop(IBaseFilter *iface)
This->stream = NULL;
}
- This->filter.state = State_Stopped;
return S_OK;
}
-static HRESULT WINAPI AviMux_Pause(IBaseFilter *iface)
+static HRESULT avi_mux_init_stream(struct strmbase_filter *iface)
{
- AviMux *This = impl_from_IBaseFilter(iface);
- FIXME("(%p)\n", This);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AviMux_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
-{
- AviMux *This = impl_from_IBaseFilter(iface);
+ AviMux *This = impl_from_strmbase_filter(iface);
HRESULT hr;
int i, stream_id;
- TRACE("(%p)->(%s)\n", This, wine_dbgstr_longlong(tStart));
-
- if(This->filter.state == State_Running)
- return S_OK;
-
if(This->mode != INTERLEAVE_FULL) {
FIXME("mode not supported (%d)\n", This->mode);
return E_NOTIMPL;
}
- if(tStart)
- FIXME("tStart parameter ignored\n");
-
for(i=0; i<This->input_pin_no; i++) {
IMediaSeeking *ms;
LONGLONG cur, stop;
@@ -694,18 +660,26 @@ static HRESULT WINAPI AviMux_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
This->avih.dwWidth = ((BITMAPINFOHEADER*)This->in[0]->strf->data)->biWidth;
This->avih.dwHeight = ((BITMAPINFOHEADER*)This->in[0]->strf->data)->biHeight;
- This->filter.state = State_Running;
return S_OK;
}
+static const struct strmbase_filter_ops filter_ops =
+{
+ .filter_get_pin = avi_mux_get_pin,
+ .filter_destroy = avi_mux_destroy,
+ .filter_query_interface = avi_mux_query_interface,
+ .filter_init_stream = avi_mux_init_stream,
+ .filter_cleanup_stream = avi_mux_cleanup_stream,
+};
+
static const IBaseFilterVtbl AviMuxVtbl = {
BaseFilterImpl_QueryInterface,
BaseFilterImpl_AddRef,
BaseFilterImpl_Release,
BaseFilterImpl_GetClassID,
- AviMux_Stop,
- AviMux_Pause,
- AviMux_Run,
+ BaseFilterImpl_Stop,
+ BaseFilterImpl_Pause,
+ BaseFilterImpl_Run,
BaseFilterImpl_GetState,
BaseFilterImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
--
2.23.0
Dec. 5, 2019
[PATCH 1/4] qcap/avico: Use strmbase filter state change methods.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/qcap/avico.c | 81 +++++++++++++++--------------------------
dlls/qcap/tests/avico.c | 8 ++--
2 files changed, 33 insertions(+), 56 deletions(-)
diff --git a/dlls/qcap/avico.c b/dlls/qcap/avico.c
index f0f60ae4394..f65f33fe442 100644
--- a/dlls/qcap/avico.c
+++ b/dlls/qcap/avico.c
@@ -56,12 +56,6 @@ static inline AVICompressor *impl_from_strmbase_filter(struct strmbase_filter *f
return CONTAINING_RECORD(filter, AVICompressor, filter);
}
-static inline AVICompressor *impl_from_IBaseFilter(IBaseFilter *iface)
-{
- struct strmbase_filter *filter = CONTAINING_RECORD(iface, struct strmbase_filter, IBaseFilter_iface);
- return impl_from_strmbase_filter(filter);
-}
-
static inline AVICompressor *impl_from_strmbase_pin(struct strmbase_pin *pin)
{
return impl_from_strmbase_filter(pin->filter);
@@ -117,57 +111,14 @@ static HRESULT fill_format_info(AVICompressor *This, VIDEOINFOHEADER *src_videoi
return S_OK;
}
-static HRESULT WINAPI AVICompressor_Stop(IBaseFilter *iface)
-{
- AVICompressor *This = impl_from_IBaseFilter(iface);
-
- TRACE("(%p)\n", This);
-
- if(This->filter.state == State_Stopped)
- return S_OK;
-
- ICCompressEnd(This->hic);
- This->filter.state = State_Stopped;
- return S_OK;
-}
-
-static HRESULT WINAPI AVICompressor_Pause(IBaseFilter *iface)
-{
- AVICompressor *This = impl_from_IBaseFilter(iface);
- FIXME("(%p)\n", This);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AVICompressor_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
-{
- AVICompressor *This = impl_from_IBaseFilter(iface);
- HRESULT hres;
-
- TRACE("(%p)->(%s)\n", This, wine_dbgstr_longlong(tStart));
-
- if(This->filter.state == State_Running)
- return S_OK;
-
- if (This->source.pAllocator && FAILED(hres = IMemAllocator_Commit(This->source.pAllocator)))
- {
- FIXME("Commit failed: %08x\n", hres);
- return hres;
- }
-
- This->frame_cnt = 0;
-
- This->filter.state = State_Running;
- return S_OK;
-}
-
static const IBaseFilterVtbl AVICompressorVtbl = {
BaseFilterImpl_QueryInterface,
BaseFilterImpl_AddRef,
BaseFilterImpl_Release,
BaseFilterImpl_GetClassID,
- AVICompressor_Stop,
- AVICompressor_Pause,
- AVICompressor_Run,
+ BaseFilterImpl_Stop,
+ BaseFilterImpl_Pause,
+ BaseFilterImpl_Run,
BaseFilterImpl_GetState,
BaseFilterImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
@@ -215,11 +166,37 @@ static HRESULT avi_compressor_query_interface(struct strmbase_filter *iface, REF
return S_OK;
}
+static HRESULT avi_compressor_init_stream(struct strmbase_filter *iface)
+{
+ AVICompressor *filter = impl_from_strmbase_filter(iface);
+ HRESULT hr;
+
+ if (filter->source.pAllocator && FAILED(hr = IMemAllocator_Commit(filter->source.pAllocator)))
+ {
+ ERR("Failed to commit allocator, hr %#x.\n", hr);
+ return hr;
+ }
+
+ filter->frame_cnt = 0;
+
+ return S_OK;
+}
+
+static HRESULT avi_compressor_cleanup_stream(struct strmbase_filter *iface)
+{
+ AVICompressor *filter = impl_from_strmbase_filter(iface);
+
+ ICCompressEnd(filter->hic);
+ return S_OK;
+}
+
static const struct strmbase_filter_ops filter_ops =
{
.filter_get_pin = avi_compressor_get_pin,
.filter_destroy = avi_compressor_destroy,
.filter_query_interface = avi_compressor_query_interface,
+ .filter_init_stream = avi_compressor_init_stream,
+ .filter_cleanup_stream = avi_compressor_cleanup_stream,
};
static AVICompressor *impl_from_IPersistPropertyBag(IPersistPropertyBag *iface)
diff --git a/dlls/qcap/tests/avico.c b/dlls/qcap/tests/avico.c
index 5c6d4aa54f4..b4f52f10210 100644
--- a/dlls/qcap/tests/avico.c
+++ b/dlls/qcap/tests/avico.c
@@ -665,11 +665,11 @@ static void test_unconnected_filter_state(IBaseFilter *filter)
ok(state == State_Stopped, "Got state %u.\n", state);
hr = IBaseFilter_Pause(filter);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IBaseFilter_GetState(filter, 0, &state);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(state == State_Paused, "Got state %u.\n", state);
+ ok(state == State_Paused, "Got state %u.\n", state);
hr = IBaseFilter_Run(filter, 0);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -679,11 +679,11 @@ static void test_unconnected_filter_state(IBaseFilter *filter)
ok(state == State_Running, "Got state %u.\n", state);
hr = IBaseFilter_Pause(filter);
- todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IBaseFilter_GetState(filter, 0, &state);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(state == State_Paused, "Got state %u.\n", state);
+ ok(state == State_Paused, "Got state %u.\n", state);
hr = IBaseFilter_Stop(filter);
ok(hr == S_OK, "Got hr %#x.\n", hr);
--
2.23.0
Dec. 5, 2019
[PATCH v3 resend] odbccp32: Implement SQLConfigDataSource/W
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/odbccp32/odbccp32.c | 121 +++++++++++++++++++++++++++++++--------
1 file changed, 97 insertions(+), 24 deletions(-)
diff --git a/dlls/odbccp32/odbccp32.c b/dlls/odbccp32/odbccp32.c
index a09d6571f3..c842872fa6 100644
--- a/dlls/odbccp32/odbccp32.c
+++ b/dlls/odbccp32/odbccp32.c
@@ -68,6 +68,9 @@ static const WCHAR odbc_error_load_lib_failed[] = {'L','o','a','d',' ','L','i','
static const WCHAR odbc_error_request_failed[] = {'R','e','q','u','e','s','t',' ','F','a','i','l','e','d',0};
static const WCHAR odbc_error_invalid_keyword[] = {'I','n','v','a','l','i','d',' ','k','e','y','w','o','r','d',' ','v','a','l','u','e',0};
+static BOOL (WINAPI *pConfigDSN)(HWND hwnd, WORD request, const char *driver, const char *attr);
+static BOOL (WINAPI *pConfigDSNW)(HWND hwnd, WORD request, const WCHAR *driver, const WCHAR *attr);
+
/* Push an error onto the error stack, taking care of ranges etc. */
static void push_error(int code, LPCWSTR msg)
{
@@ -219,30 +222,6 @@ static BOOL SQLInstall_narrow(int mode, LPSTR buffer, LPCWSTR str, WORD str_leng
return success;
}
-BOOL WINAPI SQLConfigDataSourceW(HWND hwndParent, WORD fRequest,
- LPCWSTR lpszDriver, LPCWSTR lpszAttributes)
-{
- LPCWSTR p;
-
- clear_errors();
- FIXME("%p %d %s %s\n", hwndParent, fRequest, debugstr_w(lpszDriver),
- debugstr_w(lpszAttributes));
-
- for (p = lpszAttributes; *p; p += lstrlenW(p) + 1)
- FIXME("%s\n", debugstr_w(p));
-
- return TRUE;
-}
-
-BOOL WINAPI SQLConfigDataSource(HWND hwndParent, WORD fRequest,
- LPCSTR lpszDriver, LPCSTR lpszAttributes)
-{
- FIXME("%p %d %s %s\n", hwndParent, fRequest, debugstr_a(lpszDriver),
- debugstr_a(lpszAttributes));
- clear_errors();
- return TRUE;
-}
-
static HMODULE load_config_driver(const WCHAR *driver)
{
static WCHAR reg_driver[] = {'d','r','i','v','e','r',0};
@@ -359,6 +338,100 @@ fail:
return FALSE;
}
+BOOL WINAPI SQLConfigDataSourceW(HWND hwnd, WORD request, LPCWSTR driver, LPCWSTR attributes)
+{
+ HMODULE mod;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %s, %s\n", hwnd, request, debugstr_w(driver), debugstr_w(attributes));
+ if (TRACE_ON(odbc))
+ {
+ const WCHAR *p;
+ for (p = attributes; *p; p += lstrlenW(p) + 1)
+ TRACE("%s\n", debugstr_w(p));
+ }
+
+ clear_errors();
+
+ mod = load_config_driver(driver);
+ if (!mod)
+ return FALSE;
+
+ pConfigDSNW = (void*)GetProcAddress(mod, "ConfigDSNW");
+ if(pConfigDSNW)
+ ret = pConfigDSNW(hwnd, request, driver, attributes);
+ else
+ ERR("Failed to find ConfigDSNW\n");
+
+ if (!ret)
+ push_error(ODBC_ERROR_REQUEST_FAILED, odbc_error_request_failed);
+
+ FreeLibrary(mod);
+
+ return ret;
+}
+
+BOOL WINAPI SQLConfigDataSource(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attributes)
+{
+ HMODULE mod;
+ BOOL ret = FALSE;
+ WCHAR *driverW;
+
+ TRACE("%p, %d, %s, %s\n", hwnd, request, debugstr_a(driver), debugstr_a(attributes));
+
+ if (TRACE_ON(odbc))
+ {
+ const char *p;
+ for (p = attributes; *p; p += lstrlenA(p) + 1)
+ TRACE("%s\n", debugstr_a(p));
+ }
+
+ clear_errors();
+
+ driverW = heap_strdupAtoW(driver);
+ if (!driverW)
+ {
+ push_error(ODBC_ERROR_OUT_OF_MEM, odbc_error_out_of_mem);
+ return FALSE;
+ }
+
+ mod = load_config_driver(driverW);
+ if (!mod)
+ {
+ heap_free(driverW);
+ return FALSE;
+ }
+
+ pConfigDSN = (void*)GetProcAddress(mod, "ConfigDSN");
+ if (pConfigDSN)
+ {
+ TRACE("Calling ConfigDSN\n");
+ ret = pConfigDSN(hwnd, request, driver, attributes);
+ }
+ else
+ {
+ pConfigDSNW = (void*)GetProcAddress(mod, "ConfigDSNW");
+ if (pConfigDSNW)
+ {
+ WCHAR *attr = NULL;
+ TRACE("Calling ConfigDSNW\n");
+
+ attr = SQLInstall_strdup_multi(attributes);
+ if(attr)
+ ret = pConfigDSNW(hwnd, request, driverW, attr);
+ heap_free(attr);
+ }
+ }
+
+ if (!ret)
+ push_error(ODBC_ERROR_REQUEST_FAILED, odbc_error_request_failed);
+
+ heap_free(driverW);
+ FreeLibrary(mod);
+
+ return ret;
+}
+
BOOL WINAPI SQLConfigDriverW(HWND hwnd, WORD request, LPCWSTR driver,
LPCWSTR args, LPWSTR msg, WORD msgmax, WORD *msgout)
{
--
2.17.1
Dec. 4, 2019
Re: [wine-devel] Wine staging 4.21 release
by Alan W. Irwin
On 2019-11-30 04:56-0000 Alistair Leslie-Hughes wrote:
> Binary packages for various distributions will be available from:
> https://www.winehq.org/download
>
> Summary since last release
> * Rebased to current wine 4.21 (833 patches are applied to wine vanilla)
>
> Upstreamed (Either directly from staging or fixed with a similar patch).
> * none
>
> Added:
> * [47668] kernelbase: Improve stub for ReOpenFile and add small test
> * [48138] League of Legends 9.23: Crash after champ select
> * [47970] Legends of Runeterra crashes at launch
> * [40334] AION - Wine /Unhandled exception: page fault on read access to
> 0x00000000 in 64-bit code (0x0000000000000000).
> * [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high
> memory pointers allocated
> * [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist
> package fails to load (Wine doesn't respect 44-bit user-mode VA
> limitation from Windows < 8.1)
>
> Updated:
> * d3d9-Direct3DShaderValidatorCreate9
> * winecfg-Staging
[...]
Hi Alistair:
Could you explain how these patch numbers in your report are related with each other?
For example, my initial assumption was the rebased patch number should
be equal to the corresponding number in the last report plus the added
patches in this report less the upstreamed patches in this report, i.e.,
r = r_old + a - u
where r and r_old are the current and last reported rebased patch numbers and a and u
are the current added and upstreamed patch numbers.
But looking at the last several reports that formula predicts
incorrect results with the rebased patch number changing in what looks
like a completely arbitrary way from report to report compared to the
prediction. So it appears the above formula is incorrect and/or
incomplete.
Could you let me know what the correct formula is for predicting the
rebased patch number from report to report (which helps to evaluate
the reliability of the staging patch number statistics that you
present), and if that formula depends on information (my guess is it
is the number of patches in staging that have just been deleted by the
staging maintainers because they judge those patches to not be
worthwhile) that you currently do not include in your reports, could
you include that important information in your following reports?
TIA.
Alan
__________________________
Alan W. Irwin
Programming affiliations with the FreeEOS equation-of-state
implementation for stellar interiors (freeeos.sf.net) the Time
Ephemerides project (timeephem.sf.net) PLplot scientific plotting
software package (plplot.org) the libLASi project
(unifont.org/lasi) the Loads of Linux Links project (loll.sf.net)
and the Linux Brochure Project (lbproject.sf.net)
__________________________
Linux-powered Science
__________________________
Dec. 4, 2019
[PATCH 2/2] bcrypt: Add more BCryptSignHash tests.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/bcrypt/tests/bcrypt.c | 47 +++++++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index d125e0c89d..8e495438df 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -2048,7 +2048,9 @@ static BYTE rsapublic[] =
static void test_BCryptSignHash(void)
{
static UCHAR hash[] =
- {0x7e,0xe3,0x74,0xe7,0xc5,0x0b,0x6b,0x70,0xdb,0xab,0x32,0x6d,0x1d,0x51,0xd6,0x74,0x79,0x8e,0x5b,0x4b};
+ {0x04,0xD6,0xAC,0x44,0x02,0xA9,0x2A,0x36,0x78,0x0B,0xC7,0x79,0xC8,0xEC,0x71,0x34,0x49,0xFB,0x92,0x2F};
+ static UCHAR hash_sha256[] =
+ {0x25,0x2F,0x10,0xC8,0x36,0x10,0xEB,0xCA,0x1A,0x05,0x9C,0x0B,0xAE,0x82,0x55,0xEB,0xA2,0xF9,0x5B,0xE4,0xD1,0xD7,0xBC,0xFA,0x89,0xD7,0x24,0x8A,0x82,0xD9,0xF1,0x11};
BCRYPT_PKCS1_PADDING_INFO pad;
BCRYPT_ALG_HANDLE alg;
BCRYPT_KEY_HANDLE key;
@@ -2056,6 +2058,8 @@ static void test_BCryptSignHash(void)
NTSTATUS ret;
ULONG len;
+ /* RSA */
+
ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_RSA_ALGORITHM, NULL, 0);
if (ret)
{
@@ -2087,6 +2091,14 @@ static void test_BCryptSignHash(void)
len = 0;
memset(sig, 0, sizeof(sig));
+
+ /* inference of padding info on RSA not supported */
+ ret = pBCryptSignHash(key, NULL, hash, sizeof(hash), sig, sizeof(sig), &len, 0);
+ ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
+
+ ret = pBCryptSignHash(key, &pad, hash, sizeof(hash), sig, 0, &len, BCRYPT_PAD_PKCS1);
+ ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
+
ret = pBCryptSignHash(key, &pad, hash, sizeof(hash), sig, sizeof(sig), &len, BCRYPT_PAD_PKCS1);
ok(!ret, "got %08x\n", ret);
ok(len == 64, "got %u\n", len);
@@ -2099,6 +2111,39 @@ static void test_BCryptSignHash(void)
ret = pBCryptCloseAlgorithmProvider(alg, 0);
ok(!ret, "got %08x\n", ret);
+
+ /* ECDSA */
+
+ ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_ECDSA_P256_ALGORITHM, NULL, 0);
+ if (ret)
+ {
+ win_skip("failed to open ECDSA provider: %08x\n", ret);
+ return;
+ }
+
+ ret = pBCryptGenerateKeyPair(alg, &key, 256, 0);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+
+ ret = pBCryptFinalizeKeyPair(key, 0);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+
+ memset(sig, 0, sizeof(sig));
+ len = 0;
+
+ /* automatically detects padding info */
+ ret = pBCryptSignHash(key, NULL, hash, sizeof(hash), sig, sizeof(sig), &len, 0);
+ ok (!ret, "got %08x\n", ret);
+ ok (len == 64, "got %u\n", len);
+
+ /* mismatch info (SHA-1 != SHA-256) */
+ ret = pBCryptSignHash(key, &pad, hash_sha256, sizeof(hash_sha256), sig, sizeof(sig), &len, BCRYPT_PAD_PKCS1);
+ ok (ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
+
+ ret = pBCryptDestroyKey(key);
+ ok(!ret, "got %08x\n", ret);
+
+ ret = pBCryptCloseAlgorithmProvider(alg, 0);
+ ok(!ret, "got %08x\n", ret);
}
static void test_BCryptEnumAlgorithms(void)
--
2.24.0
Dec. 4, 2019
[PATCH 1/2] bcrypt: Add support for signing hashes with ECDSA keys.
by Derek Lesho
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/bcrypt/gnutls.c | 150 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 133 insertions(+), 17 deletions(-)
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index a6a07fff19..fe16e8c435 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -92,6 +92,7 @@ MAKE_FUNCPTR(gnutls_cipher_decrypt2);
MAKE_FUNCPTR(gnutls_cipher_deinit);
MAKE_FUNCPTR(gnutls_cipher_encrypt2);
MAKE_FUNCPTR(gnutls_cipher_init);
+MAKE_FUNCPTR(gnutls_decode_rs_value);
MAKE_FUNCPTR(gnutls_global_deinit);
MAKE_FUNCPTR(gnutls_global_init);
MAKE_FUNCPTR(gnutls_global_set_log_function);
@@ -189,6 +190,7 @@ BOOL gnutls_initialize(void)
LOAD_FUNCPTR(gnutls_cipher_deinit)
LOAD_FUNCPTR(gnutls_cipher_encrypt2)
LOAD_FUNCPTR(gnutls_cipher_init)
+ LOAD_FUNCPTR(gnutls_decode_rs_value)
LOAD_FUNCPTR(gnutls_global_deinit)
LOAD_FUNCPTR(gnutls_global_init)
LOAD_FUNCPTR(gnutls_global_set_log_function)
@@ -711,6 +713,7 @@ NTSTATUS key_asymmetric_generate( struct key *key )
break;
case ALG_ID_ECDH_P256:
+ case ALG_ID_ECDSA_P256:
pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */
bitlen = GNUTLS_CURVE_TO_BITS( GNUTLS_ECC_CURVE_SECP256R1 );
break;
@@ -1029,6 +1032,23 @@ static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULO
}
}
+gnutls_digest_algorithm_t get_digest_from_id(LPCWSTR alg_id)
+{
+ if (!lstrcmpiW(alg_id, BCRYPT_SHA1_ALGORITHM))
+ return GNUTLS_DIG_SHA1;
+ if (!lstrcmpiW(alg_id, BCRYPT_SHA256_ALGORITHM))
+ return GNUTLS_DIG_SHA256;
+ if (!lstrcmpiW(alg_id, BCRYPT_SHA384_ALGORITHM))
+ return GNUTLS_DIG_SHA384;
+ if (!lstrcmpiW(alg_id, BCRYPT_SHA512_ALGORITHM))
+ return GNUTLS_DIG_SHA512;
+ if (!lstrcmpiW(alg_id, BCRYPT_MD2_ALGORITHM))
+ return GNUTLS_DIG_MD2;
+ if (!lstrcmpiW(alg_id, BCRYPT_MD5_ALGORITHM))
+ return GNUTLS_DIG_MD5;
+ return -1;
+}
+
NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULONG hash_len, UCHAR *signature,
ULONG signature_len, DWORD flags )
{
@@ -1068,11 +1088,7 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
if (!(flags & BCRYPT_PAD_PKCS1) || !info) return STATUS_INVALID_PARAMETER;
if (!info->pszAlgId) return STATUS_INVALID_SIGNATURE;
- if (!strcmpW( info->pszAlgId, BCRYPT_SHA1_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA1;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA256_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA256;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA384_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA384;
- else if (!strcmpW( info->pszAlgId, BCRYPT_SHA512_ALGORITHM )) hash_alg = GNUTLS_DIG_SHA512;
- else
+ if ((hash_alg = get_digest_from_id(info->pszAlgId)) == -1)
{
FIXME( "hash algorithm %s not supported\n", debugstr_w(info->pszAlgId) );
return STATUS_NOT_SUPPORTED;
@@ -1107,26 +1123,127 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
return (ret < 0) ? STATUS_INVALID_SIGNATURE : STATUS_SUCCESS;
}
+NTSTATUS format_gnutls_signature( enum alg_id type, gnutls_datum_t signature, UCHAR *output,
+ ULONG output_len, ULONG *ret_len)
+{
+ int err;
+ unsigned int sig_len;
+
+ switch (type)
+ {
+ case ALG_ID_RSA:
+ case ALG_ID_RSA_SIGN:
+ {
+ /* RSA */
+ if (output_len < signature.size) return STATUS_BUFFER_TOO_SMALL;
+ memcpy(output, signature.data, signature.size);
+ *ret_len = signature.size;
+ return STATUS_SUCCESS;
+ }
+ case ALG_ID_ECDSA_P256:
+ sig_len = 64;
+ goto ecc;
+ case ALG_ID_ECDSA_P384:
+ sig_len = 96;
+ ecc:
+ {
+ /* ECDSA, format as r||s */
+ gnutls_datum_t r,s;
+ unsigned int pad_size;
+
+ if ((err = pgnutls_decode_rs_value(&signature, &r, &s)))
+ {
+ ERR( "failed to get R/S values from signature %u\n", err );
+ return 0;
+ }
+
+ if (output_len < sig_len) return STATUS_BUFFER_TOO_SMALL;
+
+ /* remove prepended zero byte */
+ if (r.size % 2)
+ {
+ r.size--;
+ r.data+=1;
+ }
+ if (s.size % 2)
+ {
+ s.size--;
+ s.data+=1;
+ }
+
+ if (r.size != s.size || r.size + s.size > sig_len)
+ {
+ ERR( "we didn't get a correct signature\n" );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ pad_size = (sig_len / 2) - s.size;
+ memset(output, 0, sig_len);
+
+ memcpy(output + pad_size, r.data, r.size);
+ memcpy(output + (sig_len / 2) + pad_size, s.data, s.size);
+
+ *ret_len = sig_len;
+ return STATUS_SUCCESS;
+ }
+ default:
+ return STATUS_INTERNAL_ERROR;
+ }
+}
+
NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULONG input_len, UCHAR *output,
ULONG output_len, ULONG *ret_len, ULONG flags )
{
BCRYPT_PKCS1_PADDING_INFO *pad = padding;
gnutls_datum_t hash, signature;
+ gnutls_digest_algorithm_t hash_alg;
+ NTSTATUS status;
int ret;
- if (key->alg_id != ALG_ID_RSA && key->alg_id != ALG_ID_RSA_SIGN)
+ if (key->alg_id == ALG_ID_ECDSA_P256 || key->alg_id == ALG_ID_ECDSA_P384)
{
- FIXME( "algorithm %u not supported\n", key->alg_id );
- return STATUS_NOT_IMPLEMENTED;
+ /* With ECDSA, we find the digest algorithm from the hash length, and verify it */
+ switch (input_len)
+ {
+ case 20: hash_alg = GNUTLS_DIG_SHA1; break;
+ case 32: hash_alg = GNUTLS_DIG_SHA256; break;
+ case 48: hash_alg = GNUTLS_DIG_SHA384; break;
+ case 64: hash_alg = GNUTLS_DIG_SHA512; break;
+
+ default:
+ FIXME( "hash size %u not yet supported\n", input_len );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (flags == BCRYPT_PAD_PKCS1 && pad && pad->pszAlgId &&
+ get_digest_from_id(pad->pszAlgId) != hash_alg)
+ {
+ WARN( "incorrect hashing algorithm %s, expected %u\n", debugstr_w(pad->pszAlgId), hash_alg );
+ return STATUS_INVALID_PARAMETER;
+ }
}
- if (flags != BCRYPT_PAD_PKCS1)
+ else if (flags == BCRYPT_PAD_PKCS1)
{
- FIXME( "flags %08x not implemented\n", flags );
- return STATUS_NOT_IMPLEMENTED;
+ if (!pad || !pad->pszAlgId)
+ {
+ WARN( "padding info not found\n" );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hash_alg = get_digest_from_id(pad->pszAlgId)) == -1)
+ {
+ FIXME( "hash algorithm %s not recognized\n", debugstr_w(pad->pszAlgId) );
+ return STATUS_NOT_SUPPORTED;
+ }
+ }
+ else if (!flags)
+ {
+ WARN( "invalid flags %08x\n", flags );
+ return STATUS_INVALID_PARAMETER;
}
- if (!pad || !pad->pszAlgId || lstrcmpiW(pad->pszAlgId, BCRYPT_SHA1_ALGORITHM))
+ else
{
- FIXME( "%s padding not implemented\n", debugstr_w(pad ? pad->pszAlgId : NULL) );
+ FIXME( "flags %08x not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED;
}
@@ -1143,17 +1260,16 @@ NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULON
signature.data = NULL;
signature.size = 0;
- if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, GNUTLS_DIG_SHA1, 0, &hash, &signature )))
+ if ((ret = pgnutls_privkey_sign_hash( key->u.a.handle, hash_alg, 0, &hash, &signature )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
- if (output_len >= signature.size) memcpy( output, signature.data, signature.size );
- *ret_len = signature.size;
+ status = format_gnutls_signature(key->alg_id, signature, output, output_len, ret_len);
free( signature.data );
- return STATUS_SUCCESS;
+ return status;
}
NTSTATUS key_destroy( struct key *key )
--
2.24.0
Dec. 4, 2019
Re: [wine-devel] Wine staging 4.21 release
by Alan W. Irwin
On 2019-11-30 04:56-0000 Alistair Leslie-Hughes wrote:
> Binary packages for various distributions will be available from:
> https://www.winehq.org/download
>
> Summary since last release
> * Rebased to current wine 4.21 (833 patches are applied to wine vanilla)
>
> Upstreamed (Either directly from staging or fixed with a similar patch).
> * none
>
> Added:
> * [47668] kernelbase: Improve stub for ReOpenFile and add small test
> * [48138] League of Legends 9.23: Crash after champ select
> * [47970] Legends of Runeterra crashes at launch
> * [40334] AION - Wine /Unhandled exception: page fault on read access to
> 0x00000000 in 64-bit code (0x0000000000000000).
> * [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high
> memory pointers allocated
> * [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist
> package fails to load (Wine doesn't respect 44-bit user-mode VA
> limitation from Windows < 8.1)
>
> Updated:
> * d3d9-Direct3DShaderValidatorCreate9
> * winecfg-Staging
>
> Where can you help
> * Run Steam/Battle.net/GOG/UPlay/Epic
> * Test your favorite game.
> * Test your favorite applications.
> * Improve staging patches and get them accepted upstream.
>
> As always, if you find a bug, please report it via
> https://bugs.winehq.org
>
Hi Alistair:
Could you explain how these patch numbers are related with each other?
For example, my initial assumption was the rebased patch number should
be equal to the corresponding number in the last report plus the added
patches in this report less the upstreamed patches in this report, i.e.,
r = r_old + a - u
where r and r_old are the current and last reported rebased numbers and a and u
are the current added and upstreamed patch numbers.
But looking at the last several reports that formula predicts
incorrect results with the rebased patch number changing in what looks
like a completely arbitrary way from report to report compared to the
prediction. So it appears the above formula is incorrect and/or
incomplete.
Could you let me know what the correct formula is for predicting the
rebased patch number from report to report (which helps to evaluate
the reliability of the staging patch number statistics that you
present), and if that formula depends on information (my guess is it
is the number of patches in staging that have just been deleted by the
staging maintainers because they judge those patches to not be
worthwhile) that you currently do not include in your reports, could
you include that important information in your following reports?
Alan
__________________________
Alan W. Irwin
Programming affiliations with the FreeEOS equation-of-state
implementation for stellar interiors (freeeos.sf.net) the Time
Ephemerides project (timeephem.sf.net) PLplot scientific plotting
software package (plplot.org) the libLASi project
(unifont.org/lasi) the Loads of Linux Links project (loll.sf.net)
and the Linux Brochure Project (lbproject.sf.net)
__________________________
Linux-powered Science
__________________________
Dec. 4, 2019
Re: [PATCH 2/2] xmllite: Return syntax error on nul character in the stream.
by Nikolay Sivov
On 12/5/19 12:30 AM, Jeff Smith wrote:
> On Wed, Dec 4, 2019 at 2:04 PM Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
>> I don't think it makes sense to test for null explicitly. Any invalid
>> char for given context would be a syntax error.
> Hi Nikolay,
>
> I agree that it should work that way. However, the tests show that it
> does not. My belief is that the stream is being treated as a string,
> so when a null character encountered, it is treating as marking the
> end of the stream, even though it may actually be a part of the
> stream. My patch makes sure that condition is being covered, at least
> for the cases that are being tested.
Putting explicit null checks here and there just to fix some tests is
not worth it in my opinion.
Instead it should be a part of character range checks, as we do now.
E.g. while on whitespace,
hitting 0 char would mean you're done with whitespace node, and whatever
node is allowed or expected next
should handle it.
>
> Thanks,
> Jeff
Dec. 4, 2019
Re: [PATCH 2/2] xmllite: Return syntax error on nul character in the stream.
by Jeff Smith
On Wed, Dec 4, 2019 at 2:04 PM Nikolay Sivov <nsivov(a)codeweavers.com> wrote:
>
> I don't think it makes sense to test for null explicitly. Any invalid
> char for given context would be a syntax error.
Hi Nikolay,
I agree that it should work that way. However, the tests show that it
does not. My belief is that the stream is being treated as a string,
so when a null character encountered, it is treating as marking the
end of the stream, even though it may actually be a part of the
stream. My patch makes sure that condition is being covered, at least
for the cases that are being tested.
Thanks,
Jeff
Dec. 4, 2019
Re: [PATCH 1/2] include: Don't use the printf format attribute when compiling against msvcrt and not cross-compiling.
by Zebediah Figura
On 12/4/19 12:36 PM, Chip Davis wrote:
> December 4, 2019 12:28 PM, "Zebediah Figura" <z.figura12(a)gmail.com> wrote:
>
>> diff --git a/include/wine/debug.h b/include/wine/debug.h
>> index 1c312e9322..81c32e1816 100644
>> --- a/include/wine/debug.h
>> +++ b/include/wine/debug.h
>> @@ -92,7 +92,11 @@ struct __wine_debug_channel
>> #define __WINE_DBG_LOG(args...) \
>> wine_dbg_log( __dbcl, __dbch, __FUNCTION__, args); } } while(0)
>>
>> +#if !defined(__WINE_USE_MSVCRT) || defined(__MINGW32__)
>> #define __WINE_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
>> +#else
>> +#define __WINE_PRINTF_ATTR(fmt,args)
>> +#endif
>
> Consider using '__attribute__((format(ms_printf)))' instead. That shouldn't warn on %I, but would still give us the benefits of GCC/Clang's warning. Note that Clang does not yet support that form. I have a patch to fix that, but I need to get it upstream.
At least on gcc 9.2 ms_printf is only recognized for mingw targets. The
documentation implies this as well: "On MinGW targets, ms_printf,
ms_scanf, and ms_strftime are also present." [1]
[1]
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-F…
>
>>
>> #ifdef WINE_NO_TRACE_MSGS
>
>
> Chip
>
Dec. 4, 2019
Re: [PATCH 2/2] xmllite: Return syntax error on nul character in the stream.
by Nikolay Sivov
I don't think it makes sense to test for null explicitly. Any invalid
char for given context would be a syntax error.
Dec. 4, 2019
[PATCH 2/2] xmllite: Return syntax error on nul character in the stream.
by Jeff Smith
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/reader.c | 11 +++++++++++
dlls/xmllite/tests/reader.c | 4 ----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index eddc4d8eec..c8083f63be 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -1696,6 +1696,14 @@ static HRESULT reader_parse_pi(xmlreader *reader)
return S_OK;
}
+/* Determine if we are encountering a nul character within the stream */
+static BOOL reader_at_nul(xmlreader *reader)
+{
+ encoded_buffer *buffer = &reader->input->buffer->utf16;
+ return (buffer->cur*sizeof(WCHAR) < buffer->written &&
+ *((WCHAR*)buffer->data + buffer->cur) == 0);
+}
+
/* This one is used to parse significant whitespace nodes, like in Misc production */
static HRESULT reader_parse_whitespace(xmlreader *reader)
{
@@ -1716,6 +1724,7 @@ static HRESULT reader_parse_whitespace(xmlreader *reader)
UINT start;
reader_skipspaces(reader);
+ if (reader_at_nul(reader)) return WC_E_SYNTAX;
if (is_reader_pending(reader)) return S_OK;
start = reader->resume[XmlReadResume_Body];
@@ -1766,6 +1775,8 @@ static HRESULT reader_parse_misc(xmlreader *reader)
hr = reader_parse_comment(reader);
else if (!reader_cmp(reader, piW))
hr = reader_parse_pi(reader);
+ else if (reader_at_nul(reader))
+ return WC_E_SYNTAX;
else
break;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 88b9103e1e..7ad548d081 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1051,7 +1051,6 @@ static void test_read_nul(void)
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
@@ -1064,10 +1063,8 @@ todo_wine
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine {
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
-}
stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
@@ -1079,7 +1076,6 @@ todo_wine {
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
--
2.23.0
Dec. 4, 2019
[PATCH 1/2] xmllite/tests: Extract nul-character test from XML declaration test.
by Jeff Smith
The comments in the XML declaration test suggest that it is supposed to
be to checking for failure when no element follows the XML declaration.
However, the error being tested for is due to a nul character in the
input stream.
Create a separate test for nul-character errors, and fix the XML
declaration test accordingly.
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/xmllite/tests/reader.c | 83 +++++++++++++++++++++++++++++--------
1 file changed, 66 insertions(+), 17 deletions(-)
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 41adad1598..88b9103e1e 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -863,7 +863,6 @@ static void test_read_xmldeclaration(void)
{ {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
};
IXmlReader *reader;
- IStream *stream;
HRESULT hr;
XmlNodeType type;
UINT count = 0, len, i;
@@ -873,10 +872,7 @@ static void test_read_xmldeclaration(void)
hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
- stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
-
- hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
- ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_full);
hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "got %08x\n", hr);
@@ -968,19 +964,19 @@ static void test_read_xmldeclaration(void)
type = XmlNodeType_XmlDeclaration;
hr = IXmlReader_Read(reader, &type);
- /* newer versions return syntax error here cause document is incomplete,
- it makes more sense than invalid char error */
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(type == XmlNodeType_Whitespace, "expected XmlNodeType_Whitespace, got %s\n", type_to_str(type));
+
+ type = XmlNodeType_Whitespace;
+ hr = IXmlReader_Read(reader, &type);
todo_wine {
- ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
+ ok(hr == WC_E_ROOTELEMENT, "got %08x\n", hr);
ok(type == XmlNodeType_None, "got %d\n", type);
+ TEST_READER_STATE(reader, XmlReadState_Error);
}
- IStream_Release(stream);
/* test short variant */
- stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
-
- hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
- ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
+ set_input_string(reader, xmldecl_short);
read_node(reader, XmlNodeType_XmlDeclaration);
TEST_READER_POSITION2(reader, 1, 3, ~0u, 21);
@@ -1027,14 +1023,66 @@ todo_wine {
type = -1;
hr = IXmlReader_Read(reader, &type);
-todo_wine
- ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
+ ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
- TEST_READER_POSITION(reader, 1, 41);
+
+ IXmlReader_Release(reader);
+}
+
+static void test_read_nul(void)
+{
+ static const char xml_empty[] = "<a/>";
+ static const char xml_ws[] = "<a/> ";
+ static const char xml_comment[] = "<a/><!-- comment -->";
+ IXmlReader *reader;
+ XmlNodeType type;
+ IStream *stream;
+ HRESULT hr;
+
+ hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
+ ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+
+ stream = create_stream_on_data(xml_empty, sizeof(xml_empty));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
todo_wine
- TEST_READER_STATE(reader, XmlReadState_Error);
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+ stream = create_stream_on_data(xml_ws, sizeof(xml_ws));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine {
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+}
+
+ stream = create_stream_on_data(xml_comment, sizeof(xml_comment));
+ hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
+ ok(hr == S_OK, "got %08x\n", hr);
+ IStream_Release(stream);
+
+ read_node(reader, XmlNodeType_Element);
+ read_node(reader, XmlNodeType_Comment);
+
+ type = -1;
+ hr = IXmlReader_Read(reader, &type);
+todo_wine
+ ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "expected WC_E_SYNTAX, got 0x%08x\n", hr);
+ ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
+
IXmlReader_Release(reader);
}
@@ -2672,6 +2720,7 @@ START_TEST(reader)
test_read_pending();
test_readvaluechunk();
test_read_xmldeclaration();
+ test_read_nul();
test_reader_properties();
test_prefix();
test_namespaceuri();
--
2.23.0
Dec. 4, 2019
Re: [PATCH 1/2] include: Don't use the printf format attribute when compiling against msvcrt and not cross-compiling.
by Chip Davis
December 4, 2019 12:28 PM, "Zebediah Figura" <z.figura12(a)gmail.com> wrote:
> diff --git a/include/wine/debug.h b/include/wine/debug.h
> index 1c312e9322..81c32e1816 100644
> --- a/include/wine/debug.h
> +++ b/include/wine/debug.h
> @@ -92,7 +92,11 @@ struct __wine_debug_channel
> #define __WINE_DBG_LOG(args...) \
> wine_dbg_log( __dbcl, __dbch, __FUNCTION__, args); } } while(0)
>
> +#if !defined(__WINE_USE_MSVCRT) || defined(__MINGW32__)
> #define __WINE_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
> +#else
> +#define __WINE_PRINTF_ATTR(fmt,args)
> +#endif
Consider using '__attribute__((format(ms_printf)))' instead. That shouldn't warn on %I, but would still give us the benefits of GCC/Clang's warning. Note that Clang does not yet support that form. I have a patch to fix that, but I need to get it upstream.
>
> #ifdef WINE_NO_TRACE_MSGS
Chip
Dec. 4, 2019
[PATCH 2/2] mapi32: Use the %I length modifier to print pointer-size integers.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/mapi32/imalloc.c | 4 ++--
dlls/mapi32/mapi32_main.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/mapi32/imalloc.c b/dlls/mapi32/imalloc.c
index 3e95a6c7cd..561df1a60a 100644
--- a/dlls/mapi32/imalloc.c
+++ b/dlls/mapi32/imalloc.c
@@ -114,7 +114,7 @@ static ULONG WINAPI IMAPIMalloc_fnRelease(LPMALLOC iface)
*/
static LPVOID WINAPI IMAPIMalloc_fnAlloc(LPMALLOC iface, SIZE_T cb)
{
- TRACE("(%p)->(%ld)\n", iface, cb);
+ TRACE("(%p)->(%Id)\n", iface, cb);
return LocalAlloc(LMEM_FIXED, cb);
}
@@ -124,7 +124,7 @@ static LPVOID WINAPI IMAPIMalloc_fnAlloc(LPMALLOC iface, SIZE_T cb)
*/
static LPVOID WINAPI IMAPIMalloc_fnRealloc(LPMALLOC iface, LPVOID pv, SIZE_T cb)
{
- TRACE("(%p)->(%p, %ld)\n", iface, pv, cb);
+ TRACE("(%p)->(%p, %Id)\n", iface, pv, cb);
if (!pv)
return LocalAlloc(LMEM_FIXED, cb);
diff --git a/dlls/mapi32/mapi32_main.c b/dlls/mapi32/mapi32_main.c
index 0dcc811c24..ac83062679 100644
--- a/dlls/mapi32/mapi32_main.c
+++ b/dlls/mapi32/mapi32_main.c
@@ -129,7 +129,7 @@ HRESULT WINAPI MAPIInitialize(LPVOID init)
ULONG WINAPI MAPILogon(ULONG_PTR uiparam, LPSTR profile, LPSTR password,
FLAGS flags, ULONG reserved, LPLHANDLE session)
{
- TRACE("(0x%08lx %s %p 0x%08x 0x%08x %p)\n", uiparam,
+ TRACE("(0x%08Ix %s %p 0x%08x 0x%08x %p)\n", uiparam,
debugstr_a(profile), password, flags, reserved, session);
if (mapiFunctions.MAPILogon)
@@ -149,7 +149,7 @@ ULONG WINAPI MAPILogon(ULONG_PTR uiparam, LPSTR profile, LPSTR password,
ULONG WINAPI MAPILogoff(LHANDLE session, ULONG_PTR uiparam, FLAGS flags,
ULONG reserved )
{
- TRACE("(0x%08lx 0x%08lx 0x%08x 0x%08x)\n", session,
+ TRACE("(0x%08Ix 0x%08Ix 0x%08x 0x%08x)\n", session,
uiparam, flags, reserved);
if (mapiFunctions.MAPILogoff)
@@ -167,7 +167,7 @@ ULONG WINAPI MAPILogoff(LHANDLE session, ULONG_PTR uiparam, FLAGS flags,
HRESULT WINAPI MAPILogonEx(ULONG_PTR uiparam, LPWSTR profile,
LPWSTR password, ULONG flags, LPMAPISESSION *session)
{
- TRACE("(0x%08lx %s %p 0x%08x %p)\n", uiparam,
+ TRACE("(0x%08Ix %s %p 0x%08x %p)\n", uiparam,
debugstr_w(profile), password, flags, session);
if (mapiFunctions.MAPILogonEx)
--
2.24.0
Dec. 4, 2019
[PATCH 1/2] include: Don't use the printf format attribute when compiling against msvcrt and not cross-compiling.
by Zebediah Figura
Since it will spit out bogus warnings in the case we use Microsoft-specific
extensions.
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
include/wine/debug.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/wine/debug.h b/include/wine/debug.h
index 1c312e9322..81c32e1816 100644
--- a/include/wine/debug.h
+++ b/include/wine/debug.h
@@ -92,7 +92,11 @@ struct __wine_debug_channel
#define __WINE_DBG_LOG(args...) \
wine_dbg_log( __dbcl, __dbch, __FUNCTION__, args); } } while(0)
+#if !defined(__WINE_USE_MSVCRT) || defined(__MINGW32__)
#define __WINE_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
+#else
+#define __WINE_PRINTF_ATTR(fmt,args)
+#endif
#ifdef WINE_NO_TRACE_MSGS
--
2.24.0
Dec. 4, 2019
Re: LONG_PTR and friends
by Zebediah Figura
On 12/4/19 11:28 AM, Jacek Caban wrote:
> Hi Zebediah,
>
> On 11/26/19 7:48 PM, Zebediah Figura wrote:
>> * Both builtin and native msvcrt always support %I, but it's
>> nonstandard and it spits out warnings when you try to use it when not
>> compiling with mingw.
>
>
> I'd say that it looks like a nice solution. Since the warning is
> obviously bogus, I wonder if we should just skip format attribute in
> debug.h when __WINE_USE_MSVCRT is defined and we're not using a cross
> compiler.
Sure, makes sense. I'll try a patch along these lines.
>
>
>> * We could also cast to (void *), or cast to a 64-bit type and use
>> wine_dbgstr_longlong(), though this has the unfortunate side effect of
>> forcing us to trace in hexadecimal.
>
>
> It's not related to your original problem, but for PE builds (modules
> using -mno-cygwin to be precise), compatibility is not an issue so there
> is no reason for using wine_dbgstr_longlong(). I think we should
> consider using %ll* instead.
That would be nice, especially for places where it'd be more readable to
have decimal traces than hexadecimal. I guess we'd run into warnings
when the "long" type is used, but if we skip the format attribute as
above we won't have anything to worry about.
(Related question: why don't we just always define __int64 to "long long"?)
>
>
> Thanks,
>
> Jacek
>
>
Dec. 4, 2019
[PATCH] msxml3: all string passed to IXMLDOMDocument_load() need to be URL-unescaped
by Damjan Jovanovic
msxml3 allows URL escape sequences even for C:\ style paths.
eg. C:\Program%20Files\...
Signed-off-by: Damjan Jovanovic <damjan.jov(a)gmail.com>
---
dlls/msxml3/bsc.c | 8 ++++++--
dlls/msxml3/tests/domdoc.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 2 deletions(-)
Dec. 4, 2019
Re: LONG_PTR and friends
by Jacek Caban
Hi Zebediah,
On 11/26/19 7:48 PM, Zebediah Figura wrote:
> * Both builtin and native msvcrt always support %I, but it's
> nonstandard and it spits out warnings when you try to use it when not
> compiling with mingw.
I'd say that it looks like a nice solution. Since the warning is
obviously bogus, I wonder if we should just skip format attribute in
debug.h when __WINE_USE_MSVCRT is defined and we're not using a cross
compiler.
> * We could also cast to (void *), or cast to a 64-bit type and use
> wine_dbgstr_longlong(), though this has the unfortunate side effect of
> forcing us to trace in hexadecimal.
It's not related to your original problem, but for PE builds (modules
using -mno-cygwin to be precise), compatibility is not an issue so there
is no reason for using wine_dbgstr_longlong(). I think we should
consider using %ll* instead.
Thanks,
Jacek
Dec. 4, 2019