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