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
[PATCH tools] winegecko.php: Update for new file name scheme.
by Jacek Caban
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
winegecko.php | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)
Dec. 12, 2019
[PATCH] ntoskrnl.exe/tests: Fix typos in ok() messages.
by Andrey Gusev
Signed-off-by: Andrey Gusev <andrey.goosev(a)gmail.com>
---
dlls/ntoskrnl.exe/tests/driver.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 6827b74a3c..10f3865515 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -800,7 +800,7 @@ static void test_call_driver(DEVICE_OBJECT *device)
ok(irpsp->MajorFunction == IRP_MJ_FLUSH_BUFFERS, "MajorFunction = %u\n", irpsp->MajorFunction);
ok(!irpsp->DeviceObject, "DeviceObject = %u\n", irpsp->DeviceObject);
ok(!irpsp->FileObject, "FileObject = %u\n", irpsp->FileObject);
- ok(!irpsp->CompletionRoutine, "CompletionRouptine = %p\n", irpsp->CompletionRoutine);
+ ok(!irpsp->CompletionRoutine, "CompletionRoutine = %p\n", irpsp->CompletionRoutine);
status = IoCallDriver(device, irp);
ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
@@ -824,7 +824,7 @@ static void test_call_driver(DEVICE_OBJECT *device)
ok(irpsp->MajorFunction == IRP_MJ_FLUSH_BUFFERS, "MajorFunction = %u\n", irpsp->MajorFunction);
ok(!irpsp->DeviceObject, "DeviceObject = %u\n", irpsp->DeviceObject);
ok(!irpsp->FileObject, "FileObject = %u\n", irpsp->FileObject);
- ok(!irpsp->CompletionRoutine, "CompletionRouptine = %p\n", irpsp->CompletionRoutine);
+ ok(!irpsp->CompletionRoutine, "CompletionRoutine = %p\n", irpsp->CompletionRoutine);
status = wait_single(&event, 0);
ok(status == STATUS_TIMEOUT, "got %#x\n", status);
--
2.23.0
Dec. 12, 2019
[PATCH 2/2] msado15: Add _Command stub interface.
by Hans Leidekker
From: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/msado15/Makefile.in | 1 +
dlls/msado15/command.c | 313 +++++++++++++++++++++++++++++++
dlls/msado15/main.c | 5 +
dlls/msado15/msado15_classes.idl | 8 +
dlls/msado15/msado15_private.h | 1 +
dlls/msado15/tests/msado15.c | 27 +++
6 files changed, 355 insertions(+)
create mode 100644 dlls/msado15/command.c
diff --git a/dlls/msado15/Makefile.in b/dlls/msado15/Makefile.in
index 604f9ff018..9852e0863d 100644
--- a/dlls/msado15/Makefile.in
+++ b/dlls/msado15/Makefile.in
@@ -4,6 +4,7 @@ IMPORTS = oleaut32
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
+ command.c \
connection.c \
main.c \
recordset.c \
diff --git a/dlls/msado15/command.c b/dlls/msado15/command.c
new file mode 100644
index 0000000000..a96fd73990
--- /dev/null
+++ b/dlls/msado15/command.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2019 Alistair Leslie-Hughes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#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 command
+{
+ _Command Command_iface;
+ LONG ref;
+};
+
+static inline struct command *impl_from_Command( _Command *iface )
+{
+ return CONTAINING_RECORD( iface, struct command, Command_iface );
+}
+
+static HRESULT WINAPI command_QueryInterface( _Command *iface, REFIID riid, void **obj )
+{
+ TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
+
+ *obj = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_IDispatch) ||
+ IsEqualIID(riid, &IID__ADO) ||
+ IsEqualIID(riid, &IID_Command15) ||
+ IsEqualIID(riid, &IID_Command25) ||
+ IsEqualIID(riid, &IID__Command))
+ {
+ *obj = iface;
+ }
+ else
+ {
+ FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
+ return E_NOINTERFACE;
+ }
+
+ _Command_AddRef( iface );
+ return S_OK;
+}
+
+static ULONG WINAPI command_AddRef( _Command *iface )
+{
+ struct command *command = impl_from_Command( iface );
+ return InterlockedIncrement( &command->ref );
+}
+
+static ULONG WINAPI command_Release( _Command *iface )
+{
+ struct command *command = impl_from_Command( iface );
+ LONG ref = InterlockedDecrement( &command->ref );
+ if (!ref)
+ {
+ TRACE( "destroying %p\n", command );
+ heap_free( command );
+ }
+ return ref;
+}
+
+static HRESULT WINAPI command_GetTypeInfoCount( _Command *iface, UINT *count )
+{
+ FIXME( "%p, %p\n", iface, count );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_GetTypeInfo( _Command *iface, UINT index, LCID lcid, ITypeInfo **info )
+{
+ FIXME( "%p, %u, %u, %p\n", iface, index, lcid, info );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_GetIDsOfNames( _Command *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 command_Invoke( _Command *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 command_get_Properties( _Command *iface, Properties **props )
+{
+ FIXME( "%p, %p\n", iface, props );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_ActiveConnection( _Command *iface, _Connection **connection )
+{
+ FIXME( "%p, %p\n", iface, connection );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_putref_ActiveConnection( _Command *iface, _Connection *connection )
+{
+ FIXME( "%p, %p\n", iface, connection );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_ActiveConnection( _Command *iface, VARIANT connection )
+{
+ FIXME( "%p, %s\n", iface, debugstr_variant(&connection) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_CommandText( _Command *iface, BSTR *text )
+{
+ FIXME( "%p, %p\n", iface, text );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_CommandText( _Command *iface, BSTR text )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(text) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_CommandTimeout( _Command *iface, LONG *timeout )
+{
+ FIXME( "%p, %p\n", iface, timeout );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_CommandTimeout( _Command *iface, LONG timeout )
+{
+ FIXME( "%p, %d\n", iface, timeout );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Prepared( _Command *iface, VARIANT_BOOL *prepared )
+{
+ FIXME( "%p, %p\n", iface, prepared );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_Prepared( _Command *iface, VARIANT_BOOL prepared )
+{
+ FIXME( "%p, %d\n", iface, prepared );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_Execute( _Command *iface, VARIANT *affected, VARIANT *parameters,
+ LONG options, _Recordset **recordset )
+{
+ FIXME( "%p, %p, %p, %d, %p\n", iface, affected, parameters, options, recordset );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_CreateParameter( _Command *iface, BSTR name, DataTypeEnum type,
+ ParameterDirectionEnum direction, LONG size, VARIANT value,
+ _Parameter **parameter )
+{
+ FIXME( "%p, %s, %d, %d, %d, %p\n", iface, debugstr_w(name), type, direction, size, parameter );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Parameters( _Command *iface, Parameters **parameters )
+{
+ FIXME( "%p, %p\n", iface, parameters );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_CommandType( _Command *iface, CommandTypeEnum type )
+{
+ FIXME( "%p, %d\n", iface, type );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_CommandType( _Command *iface, CommandTypeEnum *type )
+{
+ FIXME( "%p, %p\n", iface, type );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Name(_Command *iface, BSTR *name)
+{
+ FIXME( "%p, %p\n", iface, name );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_Name( _Command *iface, BSTR name )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(name) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_State( _Command *iface, LONG *state )
+{
+ FIXME( "%p, %p\n", iface, state );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_Cancel( _Command *iface )
+{
+ FIXME( "%p\n", iface );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_putref_CommandStream( _Command *iface, IUnknown *stream )
+{
+ FIXME( "%p, %p\n", iface, stream );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_CommandStream( _Command *iface, VARIANT *stream )
+{
+ FIXME( "%p, %p\n", iface, stream );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_Dialect( _Command *iface, BSTR dialect )
+{
+ FIXME( "%p, %s\n", iface, debugstr_w(dialect) );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Dialect( _Command *iface, BSTR *dialect )
+{
+ FIXME( "%p, %p\n", iface, dialect );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_NamedParameters( _Command *iface, VARIANT_BOOL parameters )
+{
+ FIXME( "%p, %d\n", iface, parameters );
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_NamedParameters( _Command *iface, VARIANT_BOOL *parameters )
+{
+ FIXME( "%p, %p\n", iface, parameters );
+ return E_NOTIMPL;
+}
+
+static const struct _CommandVtbl command_vtbl =
+{
+ command_QueryInterface,
+ command_AddRef,
+ command_Release,
+ command_GetTypeInfoCount,
+ command_GetTypeInfo,
+ command_GetIDsOfNames,
+ command_Invoke,
+ command_get_Properties,
+ command_get_ActiveConnection,
+ command_putref_ActiveConnection,
+ command_put_ActiveConnection,
+ command_get_CommandText,
+ command_put_CommandText,
+ command_get_CommandTimeout,
+ command_put_CommandTimeout,
+ command_get_Prepared,
+ command_put_Prepared,
+ command_Execute,
+ command_CreateParameter,
+ command_get_Parameters,
+ command_put_CommandType,
+ command_get_CommandType,
+ command_get_Name,
+ command_put_Name,
+ command_get_State,
+ command_Cancel,
+ command_putref_CommandStream,
+ command_get_CommandStream,
+ command_put_Dialect,
+ command_get_Dialect,
+ command_put_NamedParameters,
+ command_get_NamedParameters
+};
+
+HRESULT Command_create( void **obj )
+{
+ struct command *command;
+
+ if (!(command = heap_alloc( sizeof(*command) ))) return E_OUTOFMEMORY;
+ command->Command_iface.lpVtbl = &command_vtbl;
+ command->ref = 1;
+
+ *obj = &command->Command_iface;
+ TRACE( "returning iface %p\n", *obj );
+ return S_OK;
+}
diff --git a/dlls/msado15/main.c b/dlls/msado15/main.c
index 32ae252337..3115474b84 100644
--- a/dlls/msado15/main.c
+++ b/dlls/msado15/main.c
@@ -117,6 +117,7 @@ static const struct IClassFactoryVtbl msadocf_vtbl =
msadocf_LockServer
};
+static struct msadocf command_cf = { { &msadocf_vtbl }, Command_create };
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 };
@@ -142,6 +143,10 @@ HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID iid, void **obj )
{
cf = &stream_cf.IClassFactory_iface;
}
+ else if (IsEqualGUID( clsid, &CLSID_Command ))
+ {
+ cf = &command_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 5ede180240..51f8bd77db 100644
--- a/dlls/msado15/msado15_classes.idl
+++ b/dlls/msado15/msado15_classes.idl
@@ -18,6 +18,14 @@
#pragma makedep register
+[
+ threading(apartment),
+ progid("ADODB.Command.6.0"),
+ vi_progid("ADODB.Command"),
+ uuid(00000507-0000-0010-8000-00aa006d2ea4)
+]
+coclass Command { interface _Command; }
+
[
threading(apartment),
progid("ADODB.Connection.6.0"),
diff --git a/dlls/msado15/msado15_private.h b/dlls/msado15/msado15_private.h
index 7239e48b53..f6c60f0304 100644
--- a/dlls/msado15/msado15_private.h
+++ b/dlls/msado15/msado15_private.h
@@ -21,6 +21,7 @@
#define MAKE_ADO_HRESULT( err ) MAKE_HRESULT( SEVERITY_ERROR, FACILITY_CONTROL, err )
+HRESULT Command_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Connection_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Recordset_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Stream_create( void ** ) DECLSPEC_HIDDEN;
diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c
index 5a1813694b..03b2828d9f 100644
--- a/dlls/msado15/tests/msado15.c
+++ b/dlls/msado15/tests/msado15.c
@@ -444,6 +444,32 @@ if (0) /* Crashes on windows */
_Connection_Release(connection);
}
+static void test_Command(void)
+{
+ HRESULT hr;
+ _Command *command;
+ _ADO *ado;
+ Command15 *command15;
+ Command25 *command25;
+
+ hr = CoCreateInstance( &CLSID_Command, NULL, CLSCTX_INPROC_SERVER, &IID__Command, (void **)&command );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = _Command_QueryInterface( command, &IID__ADO, (void **)&ado );
+ ok( hr == S_OK, "got %08x\n", hr );
+ _ADO_Release( ado );
+
+ hr = _Command_QueryInterface( command, &IID_Command15, (void **)&command15 );
+ ok( hr == S_OK, "got %08x\n", hr );
+ Command15_Release( command15 );
+
+ hr = _Command_QueryInterface( command, &IID_Command25, (void **)&command25 );
+ ok( hr == S_OK, "got %08x\n", hr );
+ Command25_Release( command25 );
+
+ _Command_Release( command );
+}
+
START_TEST(msado15)
{
CoInitialize( NULL );
@@ -451,5 +477,6 @@ START_TEST(msado15)
test_Fields();
test_Recordset();
test_Stream();
+ test_Command();
CoUninitialize();
}
--
2.20.1
Dec. 12, 2019
[PATCH 1/2] msado15: Add ISupportErrorInfo support to _Connection.
by Hans Leidekker
From: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/msado15/connection.c | 56 ++++++++++++++++++++++++++++++++----
dlls/msado15/tests/msado15.c | 5 ++--
2 files changed, 52 insertions(+), 9 deletions(-)
diff --git a/dlls/msado15/connection.c b/dlls/msado15/connection.c
index 037ab52199..73b225628c 100644
--- a/dlls/msado15/connection.c
+++ b/dlls/msado15/connection.c
@@ -32,11 +32,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(msado15);
struct connection
{
- _Connection Connection_iface;
- LONG refs;
-
- ObjectStateEnum state;
- LONG timeout;
+ _Connection Connection_iface;
+ ISupportErrorInfo ISupportErrorInfo_iface;
+ LONG refs;
+ ObjectStateEnum state;
+ LONG timeout;
};
static inline struct connection *impl_from_Connection( _Connection *iface )
@@ -44,6 +44,11 @@ static inline struct connection *impl_from_Connection( _Connection *iface )
return CONTAINING_RECORD( iface, struct connection, Connection_iface );
}
+static inline struct connection *impl_from_ISupportErrorInfo( ISupportErrorInfo *iface )
+{
+ return CONTAINING_RECORD( iface, struct connection, ISupportErrorInfo_iface );
+}
+
static ULONG WINAPI connection_AddRef( _Connection *iface )
{
struct connection *connection = impl_from_Connection( iface );
@@ -64,13 +69,18 @@ static ULONG WINAPI connection_Release( _Connection *iface )
static HRESULT WINAPI connection_QueryInterface( _Connection *iface, REFIID riid, void **obj )
{
- TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj );
+ struct connection *connection = impl_from_Connection( iface );
+ TRACE( "%p, %s, %p\n", connection, debugstr_guid(riid), obj );
if (IsEqualGUID( riid, &IID__Connection ) || IsEqualGUID( riid, &IID_IDispatch ) ||
IsEqualGUID( riid, &IID_IUnknown ))
{
*obj = iface;
}
+ else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
+ {
+ *obj = &connection->ISupportErrorInfo_iface;
+ }
else
{
FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
@@ -339,12 +349,46 @@ static const struct _ConnectionVtbl connection_vtbl =
connection_Cancel
};
+static HRESULT WINAPI supporterror_QueryInterface( ISupportErrorInfo *iface, REFIID riid, void **obj )
+{
+ struct connection *connection = impl_from_ISupportErrorInfo( iface );
+ return connection_QueryInterface( &connection->Connection_iface, riid, obj );
+}
+
+static ULONG WINAPI supporterror_AddRef( ISupportErrorInfo *iface )
+{
+ struct connection *connection = impl_from_ISupportErrorInfo( iface );
+ return connection_AddRef( &connection->Connection_iface );
+}
+
+static ULONG WINAPI supporterror_Release( ISupportErrorInfo *iface )
+{
+ struct connection *connection = impl_from_ISupportErrorInfo( iface );
+ return connection_Release( &connection->Connection_iface );
+}
+
+static HRESULT WINAPI supporterror_InterfaceSupportsErrorInfo( ISupportErrorInfo *iface, REFIID riid )
+{
+ struct connection *connection = impl_from_ISupportErrorInfo( iface );
+ FIXME( "%p, %s\n", connection, debugstr_guid(riid) );
+ return S_FALSE;
+}
+
+static const struct ISupportErrorInfoVtbl support_error_vtbl =
+{
+ supporterror_QueryInterface,
+ supporterror_AddRef,
+ supporterror_Release,
+ supporterror_InterfaceSupportsErrorInfo
+};
+
HRESULT Connection_create( void **obj )
{
struct connection *connection;
if (!(connection = heap_alloc( sizeof(*connection) ))) return E_OUTOFMEMORY;
connection->Connection_iface.lpVtbl = &connection_vtbl;
+ connection->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
connection->refs = 1;
connection->state = adStateClosed;
connection->timeout = 30;
diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c
index 4ef4762ac6..5a1813694b 100644
--- a/dlls/msado15/tests/msado15.c
+++ b/dlls/msado15/tests/msado15.c
@@ -414,9 +414,8 @@ static void test_Connection(void)
ok(hr == E_NOINTERFACE, "Unexpected IRunnableObject interface\n");
hr = _Connection_QueryInterface(connection, &IID_ISupportErrorInfo, (void**)&errorinfo);
- todo_wine ok(hr == S_OK, "Failed to get ISupportErrorInfo interface\n");
- if (hr == S_OK)
- ISupportErrorInfo_Release(errorinfo);
+ ok(hr == S_OK, "Failed to get ISupportErrorInfo interface\n");
+ ISupportErrorInfo_Release(errorinfo);
if (0) /* Crashes on windows */
{
--
2.20.1
Dec. 12, 2019
[PATCH v2 8/8] strmbase: Get rid of the "vtbl" parameter to strmbase_sink_init().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/qcap/avico.c | 24 +-------
dlls/qcap/avimux.c | 23 +-------
dlls/qcap/smartteefilter.c | 23 +-------
dlls/qedit/samplegrabber.c | 24 +-------
dlls/strmbase/pin.c | 101 +++++++++++++++++++-------------
dlls/strmbase/renderer.c | 25 +-------
dlls/strmbase/transform.c | 27 +--------
dlls/winegstreamer/gstdemux.c | 34 ++---------
dlls/wineqtdecoder/qtsplitter.c | 25 +-------
include/wine/strmbase.h | 25 +-------
10 files changed, 73 insertions(+), 258 deletions(-)
diff --git a/dlls/qcap/avico.c b/dlls/qcap/avico.c
index ecda162be86..53b8526f449 100644
--- a/dlls/qcap/avico.c
+++ b/dlls/qcap/avico.c
@@ -272,27 +272,6 @@ static const IPersistPropertyBagVtbl PersistPropertyBagVtbl = {
AVICompressorPropertyBag_Save
};
-static const IPinVtbl AVICompressorInputPinVtbl = {
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
- BaseInputPinImpl_Connect,
- BaseInputPinImpl_ReceiveConnection,
- BaseInputPinImpl_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
- BaseInputPinImpl_EndOfStream,
- BaseInputPinImpl_BeginFlush,
- BaseInputPinImpl_EndFlush,
- BaseInputPinImpl_NewSegment
-};
-
static HRESULT sink_query_accept(struct strmbase_pin *base, const AM_MEDIA_TYPE *pmt)
{
AVICompressor *This = impl_from_strmbase_pin(base);
@@ -517,8 +496,7 @@ IUnknown* WINAPI QCAP_createAVICompressor(IUnknown *outer, HRESULT *phr)
compressor->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
- strmbase_sink_init(&compressor->sink, &AVICompressorInputPinVtbl,
- &compressor->filter, sink_name, &sink_ops, NULL);
+ strmbase_sink_init(&compressor->sink, &compressor->filter, sink_name, &sink_ops, NULL);
strmbase_source_init(&compressor->source, &compressor->filter, source_name, &source_ops);
*phr = S_OK;
diff --git a/dlls/qcap/avimux.c b/dlls/qcap/avimux.c
index c17d91322bf..e402479fb17 100644
--- a/dlls/qcap/avimux.c
+++ b/dlls/qcap/avimux.c
@@ -1500,27 +1500,6 @@ static inline AviMux* impl_from_in_IPin(IPin *iface)
return impl_from_strmbase_filter(pin->filter);
}
-static const IPinVtbl AviMuxIn_PinVtbl = {
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
- BaseInputPinImpl_Connect,
- BaseInputPinImpl_ReceiveConnection,
- BaseInputPinImpl_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
- BaseInputPinImpl_EndOfStream,
- BaseInputPinImpl_BeginFlush,
- BaseInputPinImpl_EndFlush,
- BasePinImpl_NewSegment
-};
-
static inline AviMuxIn* AviMuxIn_from_IAMStreamControl(IAMStreamControl *iface)
{
return CONTAINING_RECORD(iface, AviMuxIn, IAMStreamControl_iface);
@@ -1825,7 +1804,7 @@ static HRESULT create_input_pin(AviMux *avimux)
if (!(object = heap_alloc_zero(sizeof(*object))))
return E_OUTOFMEMORY;
- strmbase_sink_init(&object->pin, &AviMuxIn_PinVtbl, &avimux->filter, name, &sink_ops, NULL);
+ strmbase_sink_init(&object->pin, &avimux->filter, name, &sink_ops, NULL);
object->pin.IMemInputPin_iface.lpVtbl = &AviMuxIn_MemInputPinVtbl;
object->IAMStreamControl_iface.lpVtbl = &AviMuxIn_AMStreamControlVtbl;
object->IPropertyBag_iface.lpVtbl = &AviMuxIn_PropertyBagVtbl;
diff --git a/dlls/qcap/smartteefilter.c b/dlls/qcap/smartteefilter.c
index e1fcea55f91..5339cb5134f 100644
--- a/dlls/qcap/smartteefilter.c
+++ b/dlls/qcap/smartteefilter.c
@@ -81,27 +81,6 @@ static const struct strmbase_filter_ops filter_ops =
.filter_destroy = smart_tee_destroy,
};
-static const IPinVtbl SmartTeeFilterInputVtbl = {
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
- BaseInputPinImpl_Connect,
- BaseInputPinImpl_ReceiveConnection,
- BaseInputPinImpl_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
- BaseInputPinImpl_EndOfStream,
- BaseInputPinImpl_BeginFlush,
- BaseInputPinImpl_EndFlush,
- BaseInputPinImpl_NewSegment
-};
-
static HRESULT sink_query_accept(struct strmbase_pin *base, const AM_MEDIA_TYPE *pmt)
{
SmartTeeFilter *This = impl_from_strmbase_pin(base);
@@ -358,7 +337,7 @@ IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr)
memset(object, 0, sizeof(*object));
strmbase_filter_init(&object->filter, outer, &CLSID_SmartTee, &filter_ops);
- strmbase_sink_init(&object->sink, &SmartTeeFilterInputVtbl, &object->filter, inputW, &sink_ops, NULL);
+ strmbase_sink_init(&object->sink, &object->filter, inputW, &sink_ops, NULL);
hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER,
&IID_IMemAllocator, (void **)&object->sink.pAllocator);
if (FAILED(hr))
diff --git a/dlls/qedit/samplegrabber.c b/dlls/qedit/samplegrabber.c
index 91b8d9dce64..bbd43e79bfd 100644
--- a/dlls/qedit/samplegrabber.c
+++ b/dlls/qedit/samplegrabber.c
@@ -473,28 +473,6 @@ static const IMemInputPinVtbl IMemInputPin_VTable =
SampleGrabber_IMemInputPin_ReceiveCanBlock,
};
-static const IPinVtbl sink_vtbl =
-{
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
- BaseInputPinImpl_Connect,
- BaseInputPinImpl_ReceiveConnection,
- BaseInputPinImpl_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
- BaseInputPinImpl_EndOfStream,
- BaseInputPinImpl_BeginFlush,
- BaseInputPinImpl_EndFlush,
- BaseInputPinImpl_NewSegment
-};
-
static inline SG_Impl *impl_from_sink_pin(struct strmbase_pin *iface)
{
return CONTAINING_RECORD(iface, SG_Impl, sink.pin);
@@ -663,7 +641,7 @@ HRESULT SampleGrabber_create(IUnknown *outer, void **out)
obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable;
- strmbase_sink_init(&obj->sink, &sink_vtbl, &obj->filter, L"In", &sink_ops, NULL);
+ strmbase_sink_init(&obj->sink, &obj->filter, L"In", &sink_ops, NULL);
strmbase_source_init(&obj->source, &obj->filter, L"Out", &source_ops);
obj->mtype.majortype = GUID_NULL;
diff --git a/dlls/strmbase/pin.c b/dlls/strmbase/pin.c
index f36e147b849..42d86eae170 100644
--- a/dlls/strmbase/pin.c
+++ b/dlls/strmbase/pin.c
@@ -82,7 +82,7 @@ HRESULT strmbase_pin_get_media_type(struct strmbase_pin *iface, unsigned int ind
return VFW_S_NO_MORE_ITEMS;
}
-HRESULT WINAPI BasePinImpl_QueryInterface(IPin *iface, REFIID iid, void **out)
+static HRESULT WINAPI pin_QueryInterface(IPin *iface, REFIID iid, void **out)
{
struct strmbase_pin *pin = impl_from_IPin(iface);
HRESULT hr;
@@ -107,19 +107,19 @@ HRESULT WINAPI BasePinImpl_QueryInterface(IPin *iface, REFIID iid, void **out)
return S_OK;
}
-ULONG WINAPI BasePinImpl_AddRef(IPin *iface)
+static ULONG WINAPI pin_AddRef(IPin *iface)
{
struct strmbase_pin *pin = impl_from_IPin(iface);
return IBaseFilter_AddRef(&pin->filter->IBaseFilter_iface);
}
-ULONG WINAPI BasePinImpl_Release(IPin *iface)
+static ULONG WINAPI pin_Release(IPin *iface)
{
struct strmbase_pin *pin = impl_from_IPin(iface);
return IBaseFilter_Release(&pin->filter->IBaseFilter_iface);
}
-HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin)
+static HRESULT WINAPI pin_ConnectedTo(IPin * iface, IPin ** ppPin)
{
struct strmbase_pin *This = impl_from_IPin(iface);
HRESULT hr;
@@ -145,7 +145,7 @@ HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin)
return hr;
}
-HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt)
+static HRESULT WINAPI pin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt)
{
struct strmbase_pin *This = impl_from_IPin(iface);
HRESULT hr;
@@ -171,7 +171,7 @@ HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt
return hr;
}
-HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin *iface, PIN_INFO *info)
+static HRESULT WINAPI pin_QueryPinInfo(IPin *iface, PIN_INFO *info)
{
struct strmbase_pin *pin = impl_from_IPin(iface);
@@ -184,7 +184,7 @@ HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin *iface, PIN_INFO *info)
return S_OK;
}
-HRESULT WINAPI BasePinImpl_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
+static HRESULT WINAPI pin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
{
struct strmbase_pin *pin = impl_from_IPin(iface);
@@ -195,7 +195,7 @@ HRESULT WINAPI BasePinImpl_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
return S_OK;
}
-HRESULT WINAPI BasePinImpl_QueryId(IPin *iface, WCHAR **id)
+static HRESULT WINAPI pin_QueryId(IPin *iface, WCHAR **id)
{
struct strmbase_pin *pin = impl_from_IPin(iface);
@@ -209,7 +209,7 @@ HRESULT WINAPI BasePinImpl_QueryId(IPin *iface, WCHAR **id)
return S_OK;
}
-HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
+static HRESULT WINAPI pin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt)
{
struct strmbase_pin *This = impl_from_IPin(iface);
@@ -219,7 +219,7 @@ HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
return (This->pFuncsTable->pin_query_accept(This, pmt) == S_OK ? S_OK : S_FALSE);
}
-HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin *iface, IEnumMediaTypes **enum_media_types)
+static HRESULT WINAPI pin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **enum_media_types)
{
struct strmbase_pin *pin = impl_from_IPin(iface);
AM_MEDIA_TYPE mt;
@@ -235,7 +235,7 @@ HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin *iface, IEnumMediaTypes **enum_me
return enum_media_types_create(pin, enum_media_types);
}
-HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
+static HRESULT WINAPI pin_QueryInternalConnections(IPin *iface, IPin **apPin, ULONG *cPin)
{
struct strmbase_pin *This = impl_from_IPin(iface);
@@ -244,14 +244,6 @@ HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin,
return E_NOTIMPL; /* to tell caller that all input pins connected to all output pins */
}
-HRESULT WINAPI BasePinImpl_NewSegment(IPin * iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
-{
- TRACE("iface %p, start %s, stop %s, rate %.16e.\n",
- iface, debugstr_time(start), debugstr_time(stop), rate);
-
- return S_OK;
-}
-
/*** OutputPin implementation ***/
static inline struct strmbase_source *impl_source_from_IPin( IPin *iface )
@@ -420,26 +412,33 @@ static HRESULT WINAPI source_EndFlush(IPin *iface)
return E_UNEXPECTED;
}
+static HRESULT WINAPI source_NewSegment(IPin * iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+{
+ TRACE("iface %p, start %s, stop %s, rate %.16e.\n",
+ iface, debugstr_time(start), debugstr_time(stop), rate);
+ return S_OK;
+}
+
static const IPinVtbl source_vtbl =
{
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
+ pin_QueryInterface,
+ pin_AddRef,
+ pin_Release,
source_Connect,
source_ReceiveConnection,
source_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
+ pin_ConnectedTo,
+ pin_ConnectionMediaType,
+ pin_QueryPinInfo,
+ pin_QueryDirection,
+ pin_QueryId,
+ pin_QueryAccept,
+ pin_EnumMediaTypes,
+ pin_QueryInternalConnections,
source_EndOfStream,
source_BeginFlush,
source_EndFlush,
- BasePinImpl_NewSegment,
+ source_NewSegment,
};
HRESULT WINAPI BaseOutputPinImpl_GetDeliveryBuffer(struct strmbase_source *This,
@@ -617,14 +616,14 @@ static struct strmbase_sink *impl_sink_from_IPin(IPin *iface)
return CONTAINING_RECORD(iface, struct strmbase_sink, pin.IPin_iface);
}
-HRESULT WINAPI BaseInputPinImpl_Connect(IPin *iface, IPin *pin, const AM_MEDIA_TYPE *pmt)
+static HRESULT WINAPI sink_Connect(IPin *iface, IPin *pin, const AM_MEDIA_TYPE *pmt)
{
ERR("(%p)->(%p, %p) outgoing connection on an input pin!\n", iface, pin, pmt);
return E_UNEXPECTED;
}
-HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
+static HRESULT WINAPI sink_ReceiveConnection(IPin *iface, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
{
struct strmbase_sink *This = impl_sink_from_IPin(iface);
PIN_DIRECTION pindirReceive;
@@ -678,7 +677,7 @@ HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceiveP
return hr;
}
-HRESULT WINAPI BaseInputPinImpl_Disconnect(IPin *iface)
+static HRESULT WINAPI sink_Disconnect(IPin *iface)
{
struct strmbase_sink *pin = impl_sink_from_IPin(iface);
HRESULT hr;
@@ -711,7 +710,7 @@ static HRESULT deliver_endofstream(IPin* pin, LPVOID unused)
return IPin_EndOfStream( pin );
}
-HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface)
+static HRESULT WINAPI sink_EndOfStream(IPin *iface)
{
struct strmbase_sink *This = impl_sink_from_IPin(iface);
HRESULT hr = S_OK;
@@ -736,7 +735,7 @@ static HRESULT deliver_beginflush(IPin* pin, LPVOID unused)
return IPin_BeginFlush( pin );
}
-HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface)
+static HRESULT WINAPI sink_BeginFlush(IPin *iface)
{
struct strmbase_sink *This = impl_sink_from_IPin(iface);
HRESULT hr;
@@ -759,7 +758,7 @@ static HRESULT deliver_endflush(IPin* pin, LPVOID unused)
return IPin_EndFlush( pin );
}
-HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface)
+static HRESULT WINAPI sink_EndFlush(IPin * iface)
{
struct strmbase_sink *This = impl_sink_from_IPin(iface);
HRESULT hr;
@@ -789,7 +788,7 @@ static HRESULT deliver_newsegment(IPin *pin, LPVOID data)
return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate);
}
-HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+static HRESULT WINAPI sink_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
{
struct strmbase_sink *pin = impl_sink_from_IPin(iface);
newsegmentargs args;
@@ -807,6 +806,28 @@ HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME start, R
return SendFurther(pin, deliver_newsegment, &args);
}
+static const IPinVtbl sink_vtbl =
+{
+ pin_QueryInterface,
+ pin_AddRef,
+ pin_Release,
+ sink_Connect,
+ sink_ReceiveConnection,
+ sink_Disconnect,
+ pin_ConnectedTo,
+ pin_ConnectionMediaType,
+ pin_QueryPinInfo,
+ pin_QueryDirection,
+ pin_QueryId,
+ pin_QueryAccept,
+ pin_EnumMediaTypes,
+ pin_QueryInternalConnections,
+ sink_EndOfStream,
+ sink_BeginFlush,
+ sink_EndFlush,
+ sink_NewSegment,
+};
+
/*** IMemInputPin implementation ***/
static inline struct strmbase_sink *impl_from_IMemInputPin(IMemInputPin *iface)
@@ -938,11 +959,11 @@ static const IMemInputPinVtbl MemInputPin_Vtbl =
MemInputPin_ReceiveCanBlock
};
-void strmbase_sink_init(struct strmbase_sink *pin, const IPinVtbl *vtbl, struct strmbase_filter *filter,
+void strmbase_sink_init(struct strmbase_sink *pin, struct strmbase_filter *filter,
const WCHAR *name, const struct strmbase_sink_ops *func_table, IMemAllocator *allocator)
{
memset(pin, 0, sizeof(*pin));
- pin->pin.IPin_iface.lpVtbl = vtbl;
+ pin->pin.IPin_iface.lpVtbl = &sink_vtbl;
pin->pin.filter = filter;
pin->pin.dir = PINDIR_INPUT;
lstrcpyW(pin->pin.name, name);
diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c
index 3c9692029dd..3fd8af2c1c2 100644
--- a/dlls/strmbase/renderer.c
+++ b/dlls/strmbase/renderer.c
@@ -40,28 +40,6 @@ static inline struct strmbase_renderer *impl_from_IPin(IPin *iface)
return CONTAINING_RECORD(iface, struct strmbase_renderer, sink.pin.IPin_iface);
}
-static const IPinVtbl BaseRenderer_InputPin_Vtbl =
-{
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
- BaseInputPinImpl_Connect,
- BaseInputPinImpl_ReceiveConnection,
- BaseInputPinImpl_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
- BaseInputPinImpl_EndOfStream,
- BaseInputPinImpl_BeginFlush,
- BaseInputPinImpl_EndFlush,
- BaseInputPinImpl_NewSegment
-};
-
static struct strmbase_pin *renderer_get_pin(struct strmbase_filter *iface, unsigned int index)
{
struct strmbase_renderer *filter = impl_from_strmbase_filter(iface);
@@ -441,8 +419,7 @@ HRESULT WINAPI strmbase_renderer_init(struct strmbase_renderer *filter, IUnknown
filter->pFuncsTable = ops;
- strmbase_sink_init(&filter->sink, &BaseRenderer_InputPin_Vtbl, &filter->filter,
- sink_name, &sink_ops, NULL);
+ strmbase_sink_init(&filter->sink, &filter->filter, sink_name, &sink_ops, NULL);
hr = CreatePosPassThru(outer ? outer : (IUnknown *)&filter->filter.IBaseFilter_iface,
TRUE, &filter->sink.pin.IPin_iface, &filter->pPosition);
diff --git a/dlls/strmbase/transform.c b/dlls/strmbase/transform.c
index 13e7be21789..6082a142dc9 100644
--- a/dlls/strmbase/transform.c
+++ b/dlls/strmbase/transform.c
@@ -26,8 +26,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
static const WCHAR wcsInputPinName[] = {'I','n',0};
static const WCHAR wcsOutputPinName[] = {'O','u','t',0};
-static const IPinVtbl TransformFilter_InputPin_Vtbl;
-
static inline TransformFilter *impl_from_strmbase_filter(struct strmbase_filter *iface)
{
return CONTAINING_RECORD(iface, TransformFilter, filter);
@@ -407,8 +405,7 @@ static HRESULT strmbase_transform_init(IUnknown *outer, const CLSID *clsid,
filter->pFuncsTable = func_table;
ZeroMemory(&filter->pmt, sizeof(filter->pmt));
- strmbase_sink_init(&filter->sink, &TransformFilter_InputPin_Vtbl, &filter->filter,
- wcsInputPinName, &sink_ops, NULL);
+ strmbase_sink_init(&filter->sink, &filter->filter, wcsInputPinName, &sink_ops, NULL);
strmbase_source_init(&filter->source, &filter->filter, wcsOutputPinName, &source_ops);
filter->source_IQualityControl_iface.lpVtbl = &source_qc_vtbl;
@@ -458,25 +455,3 @@ HRESULT strmbase_transform_create(LONG filter_size, IUnknown *outer, const CLSID
CoTaskMemFree(pTf);
return E_FAIL;
}
-
-static const IPinVtbl TransformFilter_InputPin_Vtbl =
-{
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
- BaseInputPinImpl_Connect,
- BaseInputPinImpl_ReceiveConnection,
- BaseInputPinImpl_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
- BaseInputPinImpl_EndOfStream,
- BaseInputPinImpl_BeginFlush,
- BaseInputPinImpl_EndFlush,
- BaseInputPinImpl_NewSegment
-};
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index 1eae0dae9af..3945d9da8fa 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -97,7 +97,6 @@ const char* media_quark_string = "media-sample";
static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
static const IMediaSeekingVtbl GST_Seeking_Vtbl;
-static const IPinVtbl GST_InputPin_Vtbl;
static const IQualityControlVtbl GSTOutPin_QualityControl_Vtbl;
static struct gstdemux_source *create_pin(struct gstdemux *filter, const WCHAR *name);
@@ -1502,8 +1501,7 @@ IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *outer, HRESULT *phr)
}
strmbase_filter_init(&object->filter, outer, &CLSID_Gstreamer_Splitter, &filter_ops);
- strmbase_sink_init(&object->sink, &GST_InputPin_Vtbl, &object->filter,
- wcsInputPinName, &sink_ops, NULL);
+ strmbase_sink_init(&object->sink, &object->filter, wcsInputPinName, &sink_ops, NULL);
object->no_more_pads_event = CreateEventW(NULL, FALSE, FALSE, NULL);
object->init_gst = gstdecoder_init_gst;
@@ -1967,27 +1965,6 @@ static HRESULT GST_RemoveOutputPins(struct gstdemux *This)
return S_OK;
}
-static const IPinVtbl GST_InputPin_Vtbl = {
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
- BaseInputPinImpl_Connect,
- BaseInputPinImpl_ReceiveConnection,
- BaseInputPinImpl_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
- BaseInputPinImpl_EndOfStream,
- BaseInputPinImpl_BeginFlush,
- BaseInputPinImpl_EndFlush,
- BaseInputPinImpl_NewSegment
-};
-
pthread_mutex_t cb_list_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cb_list_cond = PTHREAD_COND_INITIALIZER;
struct list cb_list = LIST_INIT(cb_list);
@@ -2235,8 +2212,7 @@ IUnknown * CALLBACK wave_parser_create(IUnknown *outer, HRESULT *phr)
}
strmbase_filter_init(&object->filter, outer, &CLSID_WAVEParser, &filter_ops);
- strmbase_sink_init(&object->sink, &GST_InputPin_Vtbl, &object->filter,
- sink_name, &wave_parser_sink_ops, NULL);
+ strmbase_sink_init(&object->sink, &object->filter, sink_name, &wave_parser_sink_ops, NULL);
object->init_gst = wave_parser_init_gst;
*phr = S_OK;
@@ -2339,8 +2315,7 @@ IUnknown * CALLBACK avi_splitter_create(IUnknown *outer, HRESULT *phr)
}
strmbase_filter_init(&object->filter, outer, &CLSID_AviSplitter, &filter_ops);
- strmbase_sink_init(&object->sink, &GST_InputPin_Vtbl, &object->filter,
- sink_name, &avi_splitter_sink_ops, NULL);
+ strmbase_sink_init(&object->sink, &object->filter, sink_name, &avi_splitter_sink_ops, NULL);
object->no_more_pads_event = CreateEventW(NULL, FALSE, FALSE, NULL);
object->init_gst = avi_splitter_init_gst;
*phr = S_OK;
@@ -2475,8 +2450,7 @@ IUnknown * CALLBACK mpeg_splitter_create(IUnknown *outer, HRESULT *phr)
}
strmbase_filter_init(&object->filter, outer, &CLSID_MPEG1Splitter, &mpeg_splitter_ops);
- strmbase_sink_init(&object->sink, &GST_InputPin_Vtbl, &object->filter,
- sink_name, &mpeg_splitter_sink_ops, NULL);
+ strmbase_sink_init(&object->sink, &object->filter, sink_name, &mpeg_splitter_sink_ops, NULL);
object->IAMStreamSelect_iface.lpVtbl = &stream_select_vtbl;
object->duration_event = CreateEventW(NULL, FALSE, FALSE, NULL);
diff --git a/dlls/wineqtdecoder/qtsplitter.c b/dlls/wineqtdecoder/qtsplitter.c
index df6e8ea5d24..1421e0bf53c 100644
--- a/dlls/wineqtdecoder/qtsplitter.c
+++ b/dlls/wineqtdecoder/qtsplitter.c
@@ -171,7 +171,6 @@ typedef struct QTSplitter {
HANDLE splitterThread;
} QTSplitter;
-static const IPinVtbl QT_InputPin_Vtbl;
static const IBaseFilterVtbl QT_Vtbl;
static const IMediaSeekingVtbl QT_Seeking_Vtbl;
@@ -421,8 +420,7 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *outer, HRESULT *phr)
ZeroMemory(This,sizeof(*This));
strmbase_filter_init(&This->filter, outer, &CLSID_QTSplitter, &filter_ops);
- strmbase_sink_init(&This->pInputPin.pin, &QT_InputPin_Vtbl, &This->filter,
- wcsInputPinName, &sink_ops, NULL);
+ strmbase_sink_init(&This->pInputPin.pin, &This->filter, wcsInputPinName, &sink_ops, NULL);
InitializeCriticalSection(&This->csReceive);
This->csReceive.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": QTSplitter.csReceive");
@@ -1030,27 +1028,6 @@ static HRESULT QT_Process_Movie(QTSplitter* filter)
return hr;
}
-static const IPinVtbl QT_InputPin_Vtbl = {
- BasePinImpl_QueryInterface,
- BasePinImpl_AddRef,
- BasePinImpl_Release,
- BaseInputPinImpl_Connect,
- BaseInputPinImpl_ReceiveConnection,
- BaseInputPinImpl_Disconnect,
- BasePinImpl_ConnectedTo,
- BasePinImpl_ConnectionMediaType,
- BasePinImpl_QueryPinInfo,
- BasePinImpl_QueryDirection,
- BasePinImpl_QueryId,
- BasePinImpl_QueryAccept,
- BasePinImpl_EnumMediaTypes,
- BasePinImpl_QueryInternalConnections,
- BaseInputPinImpl_EndOfStream,
- BaseInputPinImpl_BeginFlush,
- BaseInputPinImpl_EndFlush,
- BaseInputPinImpl_NewSegment
-};
-
static inline QTOutPin *impl_source_from_strmbase_pin(struct strmbase_pin *iface)
{
return CONTAINING_RECORD(iface, QTOutPin, pin.pin);
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index c01ef6133f4..48d7638ae16 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -103,20 +103,6 @@ struct strmbase_sink_ops
/* Base Pin */
HRESULT strmbase_pin_get_media_type(struct strmbase_pin *pin, unsigned int index, AM_MEDIA_TYPE *mt);
-LONG WINAPI BasePinImpl_GetMediaTypeVersion(struct strmbase_pin *pin);
-HRESULT WINAPI BasePinImpl_QueryInterface(IPin *iface, REFIID iid, void **out);
-ULONG WINAPI BasePinImpl_AddRef(IPin *iface);
-ULONG WINAPI BasePinImpl_Release(IPin *iface);
-HRESULT WINAPI BaseInputPinImpl_Disconnect(IPin * iface);
-HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin);
-HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo);
-HRESULT WINAPI BasePinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir);
-HRESULT WINAPI BasePinImpl_QueryId(IPin * iface, LPWSTR * Id);
-HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum);
-HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin);
-HRESULT WINAPI BasePinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
HRESULT WINAPI BaseOutputPinImpl_GetDeliveryBuffer(struct strmbase_source *pin,
IMediaSample **sample, REFERENCE_TIME *start, REFERENCE_TIME *stop, DWORD flags);
@@ -130,16 +116,7 @@ void strmbase_source_cleanup(struct strmbase_source *pin);
void strmbase_source_init(struct strmbase_source *pin, struct strmbase_filter *filter,
const WCHAR *name, const struct strmbase_source_ops *func_table);
-/* Base Input Pin */
-HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
-HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface);
-HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface);
-HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface);
-HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
-
-void strmbase_sink_init(struct strmbase_sink *pin, const IPinVtbl *vtbl, struct strmbase_filter *filter,
+void strmbase_sink_init(struct strmbase_sink *pin, struct strmbase_filter *filter,
const WCHAR *name, const struct strmbase_sink_ops *ops, IMemAllocator *allocator);
void strmbase_sink_cleanup(struct strmbase_sink *pin);
--
2.24.0
Dec. 12, 2019
[PATCH v2 7/8] wineqtdecoder: Use base sink streaming methods.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/wineqtdecoder/qtsplitter.c | 33 ++++-----------------------------
1 file changed, 4 insertions(+), 29 deletions(-)
diff --git a/dlls/wineqtdecoder/qtsplitter.c b/dlls/wineqtdecoder/qtsplitter.c
index 01ec4c2cede..df6e8ea5d24 100644
--- a/dlls/wineqtdecoder/qtsplitter.c
+++ b/dlls/wineqtdecoder/qtsplitter.c
@@ -1030,31 +1030,6 @@ static HRESULT QT_Process_Movie(QTSplitter* filter)
return hr;
}
-static HRESULT WINAPI QTInPin_EndOfStream(IPin *iface)
-{
- FIXME("iface %p, stub!\n", iface);
- return S_OK;
-}
-
-static HRESULT WINAPI QTInPin_BeginFlush(IPin *iface)
-{
- FIXME("iface %p, stub!\n", iface);
- return S_OK;
-}
-
-static HRESULT WINAPI QTInPin_EndFlush(IPin *iface)
-{
- FIXME("iface %p, stub!\n", iface);
- return S_OK;
-}
-
-static HRESULT WINAPI QTInPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
-{
- BasePinImpl_NewSegment(iface, tStart, tStop, dRate);
- FIXME("iface %p, stub!\n", iface);
- return S_OK;
-}
-
static const IPinVtbl QT_InputPin_Vtbl = {
BasePinImpl_QueryInterface,
BasePinImpl_AddRef,
@@ -1070,10 +1045,10 @@ static const IPinVtbl QT_InputPin_Vtbl = {
BasePinImpl_QueryAccept,
BasePinImpl_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
- QTInPin_EndOfStream,
- QTInPin_BeginFlush,
- QTInPin_EndFlush,
- QTInPin_NewSegment
+ BaseInputPinImpl_EndOfStream,
+ BaseInputPinImpl_BeginFlush,
+ BaseInputPinImpl_EndFlush,
+ BaseInputPinImpl_NewSegment
};
static inline QTOutPin *impl_source_from_strmbase_pin(struct strmbase_pin *iface)
--
2.24.0
Dec. 12, 2019
[PATCH v2 6/8] winegstreamer: Use base sink streaming methods.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/winegstreamer/gstdemux.c | 36 ++++-------------------------------
1 file changed, 4 insertions(+), 32 deletions(-)
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index fb60d69e2ac..1eae0dae9af 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -1967,34 +1967,6 @@ static HRESULT GST_RemoveOutputPins(struct gstdemux *This)
return S_OK;
}
-static HRESULT WINAPI GSTInPin_EndOfStream(IPin *iface)
-{
- FIXME("iface %p, stub!\n", iface);
- return S_OK;
-}
-
-static HRESULT WINAPI GSTInPin_BeginFlush(IPin *iface)
-{
- FIXME("iface %p, stub!\n", iface);
- return S_OK;
-}
-
-static HRESULT WINAPI GSTInPin_EndFlush(IPin *iface)
-{
- FIXME("iface %p, stub!\n", iface);
- return S_OK;
-}
-
-static HRESULT WINAPI GSTInPin_NewSegment(IPin *iface, REFERENCE_TIME start,
- REFERENCE_TIME stop, double rate)
-{
- FIXME("iface %p, start %s, stop %s, rate %.16e, stub!\n",
- iface, wine_dbgstr_longlong(start), wine_dbgstr_longlong(stop), rate);
-
- BasePinImpl_NewSegment(iface, start, stop, rate);
- return S_OK;
-}
-
static const IPinVtbl GST_InputPin_Vtbl = {
BasePinImpl_QueryInterface,
BasePinImpl_AddRef,
@@ -2010,10 +1982,10 @@ static const IPinVtbl GST_InputPin_Vtbl = {
BasePinImpl_QueryAccept,
BasePinImpl_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
- GSTInPin_EndOfStream,
- GSTInPin_BeginFlush,
- GSTInPin_EndFlush,
- GSTInPin_NewSegment
+ BaseInputPinImpl_EndOfStream,
+ BaseInputPinImpl_BeginFlush,
+ BaseInputPinImpl_EndFlush,
+ BaseInputPinImpl_NewSegment
};
pthread_mutex_t cb_list_lock = PTHREAD_MUTEX_INITIALIZER;
--
2.24.0
Dec. 12, 2019
[PATCH v2 5/8] strmbase/renderer: Use base sink streaming methods.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/strmbase/renderer.c | 142 +++++++++++++++++++--------------------
1 file changed, 68 insertions(+), 74 deletions(-)
diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c
index 7b9736ccfb2..3c9692029dd 100644
--- a/dlls/strmbase/renderer.c
+++ b/dlls/strmbase/renderer.c
@@ -40,77 +40,6 @@ static inline struct strmbase_renderer *impl_from_IPin(IPin *iface)
return CONTAINING_RECORD(iface, struct strmbase_renderer, sink.pin.IPin_iface);
}
-static HRESULT WINAPI BaseRenderer_InputPin_EndOfStream(IPin * iface)
-{
- struct strmbase_renderer *filter = impl_from_IPin(iface);
- IFilterGraph *graph = filter->filter.filterInfo.pGraph;
- IMediaEventSink *event_sink;
- HRESULT hr = S_OK;
-
- TRACE("iface %p.\n", iface);
-
- EnterCriticalSection(&filter->csRenderLock);
- filter->eos = TRUE;
-
- if (graph && SUCCEEDED(IFilterGraph_QueryInterface(graph,
- &IID_IMediaEventSink, (void **)&event_sink)))
- {
- IMediaEventSink_Notify(event_sink, EC_COMPLETE, S_OK,
- (LONG_PTR)&filter->filter.IBaseFilter_iface);
- IMediaEventSink_Release(event_sink);
- }
- RendererPosPassThru_EOS(filter->pPosition);
- SetEvent(filter->state_event);
-
- if (filter->pFuncsTable->pfnEndOfStream)
- hr = filter->pFuncsTable->pfnEndOfStream(filter);
- LeaveCriticalSection(&filter->csRenderLock);
- return hr;
-}
-
-static HRESULT WINAPI BaseRenderer_InputPin_BeginFlush(IPin * iface)
-{
- struct strmbase_renderer *pFilter = impl_from_IPin(iface);
- HRESULT hr;
-
- TRACE("iface %p.\n", iface);
-
- EnterCriticalSection(&pFilter->filter.csFilter);
- hr = BaseInputPinImpl_BeginFlush(iface);
- if (SUCCEEDED(hr))
- {
- BaseRendererImpl_ClearPendingSample(pFilter);
- SetEvent(pFilter->flush_event);
- }
- LeaveCriticalSection(&pFilter->filter.csFilter);
- return hr;
-}
-
-static HRESULT WINAPI BaseRenderer_InputPin_EndFlush(IPin * iface)
-{
- struct strmbase_renderer *pFilter = impl_from_IPin(iface);
- HRESULT hr;
-
- TRACE("iface %p.\n", iface);
-
- EnterCriticalSection(&pFilter->filter.csFilter);
- EnterCriticalSection(&pFilter->csRenderLock);
- pFilter->eos = FALSE;
- hr = BaseInputPinImpl_EndFlush(iface);
- if (SUCCEEDED(hr))
- {
- QualityControlRender_Start(pFilter->qcimpl, pFilter->stream_start);
- RendererPosPassThru_ResetMediaTime(pFilter->pPosition);
- ResetEvent(pFilter->flush_event);
-
- if (pFilter->pFuncsTable->pfnEndFlush)
- hr = pFilter->pFuncsTable->pfnEndFlush(pFilter);
- }
- LeaveCriticalSection(&pFilter->csRenderLock);
- LeaveCriticalSection(&pFilter->filter.csFilter);
- return hr;
-}
-
static const IPinVtbl BaseRenderer_InputPin_Vtbl =
{
BasePinImpl_QueryInterface,
@@ -127,9 +56,9 @@ static const IPinVtbl BaseRenderer_InputPin_Vtbl =
BasePinImpl_QueryAccept,
BasePinImpl_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
- BaseRenderer_InputPin_EndOfStream,
- BaseRenderer_InputPin_BeginFlush,
- BaseRenderer_InputPin_EndFlush,
+ BaseInputPinImpl_EndOfStream,
+ BaseInputPinImpl_BeginFlush,
+ BaseInputPinImpl_EndFlush,
BaseInputPinImpl_NewSegment
};
@@ -289,6 +218,68 @@ static void sink_disconnect(struct strmbase_sink *iface)
filter->pFuncsTable->pfnBreakConnect(filter);
}
+static HRESULT sink_eos(struct strmbase_sink *iface)
+{
+ struct strmbase_renderer *filter = impl_from_IPin(&iface->pin.IPin_iface);
+ IFilterGraph *graph = filter->filter.filterInfo.pGraph;
+ IMediaEventSink *event_sink;
+ HRESULT hr;
+
+ EnterCriticalSection(&filter->csRenderLock);
+
+ filter->eos = TRUE;
+
+ if (graph && SUCCEEDED(IFilterGraph_QueryInterface(graph,
+ &IID_IMediaEventSink, (void **)&event_sink)))
+ {
+ IMediaEventSink_Notify(event_sink, EC_COMPLETE, S_OK,
+ (LONG_PTR)&filter->filter.IBaseFilter_iface);
+ IMediaEventSink_Release(event_sink);
+ }
+ RendererPosPassThru_EOS(filter->pPosition);
+ SetEvent(filter->state_event);
+
+ if (filter->pFuncsTable->pfnEndOfStream)
+ hr = filter->pFuncsTable->pfnEndOfStream(filter);
+
+ LeaveCriticalSection(&filter->csRenderLock);
+ return hr;
+}
+
+static HRESULT sink_begin_flush(struct strmbase_sink *iface)
+{
+ struct strmbase_renderer *filter = impl_from_IPin(&iface->pin.IPin_iface);
+
+ EnterCriticalSection(&filter->filter.csFilter);
+
+ BaseRendererImpl_ClearPendingSample(filter);
+ SetEvent(filter->flush_event);
+
+ LeaveCriticalSection(&filter->filter.csFilter);
+ return S_OK;
+}
+
+static HRESULT sink_end_flush(struct strmbase_sink *iface)
+{
+ struct strmbase_renderer *filter = impl_from_IPin(&iface->pin.IPin_iface);
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&filter->filter.csFilter);
+ EnterCriticalSection(&filter->csRenderLock);
+
+ filter->eos = FALSE;
+ QualityControlRender_Start(filter->qcimpl, filter->stream_start);
+ RendererPosPassThru_ResetMediaTime(filter->pPosition);
+ ResetEvent(filter->flush_event);
+
+ if (filter->pFuncsTable->pfnEndFlush)
+ hr = filter->pFuncsTable->pfnEndFlush(filter);
+
+ LeaveCriticalSection(&filter->csRenderLock);
+ LeaveCriticalSection(&filter->filter.csFilter);
+ return hr;
+}
+
static const struct strmbase_sink_ops sink_ops =
{
.base.pin_query_accept = sink_query_accept,
@@ -297,6 +288,9 @@ static const struct strmbase_sink_ops sink_ops =
.pfnReceive = BaseRenderer_Receive,
.sink_connect = sink_connect,
.sink_disconnect = sink_disconnect,
+ .sink_eos = sink_eos,
+ .sink_begin_flush = sink_begin_flush,
+ .sink_end_flush = sink_end_flush,
};
void strmbase_renderer_cleanup(struct strmbase_renderer *filter)
--
2.24.0
Dec. 12, 2019
[PATCH v2 4/8] strmbase/transform: Use base sink streaming methods.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/strmbase/transform.c | 120 ++++++++++++++++++--------------------
1 file changed, 58 insertions(+), 62 deletions(-)
diff --git a/dlls/strmbase/transform.c b/dlls/strmbase/transform.c
index 993e30202bc..13e7be21789 100644
--- a/dlls/strmbase/transform.c
+++ b/dlls/strmbase/transform.c
@@ -229,6 +229,56 @@ static void sink_disconnect(struct strmbase_sink *iface)
filter->pFuncsTable->pfnBreakConnect(filter, PINDIR_INPUT);
}
+static HRESULT sink_eos(struct strmbase_sink *iface)
+{
+ TransformFilter *filter = impl_from_sink_IPin(&iface->pin.IPin_iface);
+
+ if (filter->source.pin.peer)
+ return IPin_EndOfStream(filter->source.pin.peer);
+ return VFW_E_NOT_CONNECTED;
+}
+
+static HRESULT sink_begin_flush(struct strmbase_sink *iface)
+{
+ TransformFilter *filter = impl_from_sink_IPin(&iface->pin.IPin_iface);
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&filter->filter.csFilter);
+ if (filter->pFuncsTable->pfnBeginFlush)
+ hr = filter->pFuncsTable->pfnBeginFlush(filter);
+ if (SUCCEEDED(hr) && filter->source.pin.peer)
+ hr = IPin_BeginFlush(filter->source.pin.peer);
+ LeaveCriticalSection(&filter->filter.csFilter);
+ return hr;
+}
+
+static HRESULT sink_end_flush(struct strmbase_sink *iface)
+{
+ TransformFilter *filter = impl_from_sink_IPin(&iface->pin.IPin_iface);
+ HRESULT hr = S_OK;
+
+ EnterCriticalSection(&filter->filter.csFilter);
+ if (filter->pFuncsTable->pfnEndFlush)
+ hr = filter->pFuncsTable->pfnEndFlush(filter);
+ if (SUCCEEDED(hr) && filter->source.pin.peer)
+ hr = IPin_EndFlush(filter->source.pin.peer);
+ LeaveCriticalSection(&filter->filter.csFilter);
+ return hr;
+}
+
+static HRESULT sink_new_segment(struct strmbase_sink *iface,
+ REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+{
+ TransformFilter *filter = impl_from_sink_IPin(&iface->pin.IPin_iface);
+ HRESULT hr = S_OK;
+
+ if (filter->pFuncsTable->pfnNewSegment)
+ hr = filter->pFuncsTable->pfnNewSegment(filter, start, stop, rate);
+ if (SUCCEEDED(hr) && filter->source.pin.peer)
+ hr = IPin_NewSegment(filter->source.pin.peer, start, stop, rate);
+ return hr;
+}
+
static const struct strmbase_sink_ops sink_ops =
{
.base.pin_query_accept = sink_query_accept,
@@ -237,6 +287,10 @@ static const struct strmbase_sink_ops sink_ops =
.pfnReceive = TransformFilter_Input_Receive,
.sink_connect = sink_connect,
.sink_disconnect = sink_disconnect,
+ .sink_eos = sink_eos,
+ .sink_begin_flush = sink_begin_flush,
+ .sink_end_flush = sink_end_flush,
+ .sink_new_segment = sink_new_segment,
};
static HRESULT source_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
@@ -405,64 +459,6 @@ HRESULT strmbase_transform_create(LONG filter_size, IUnknown *outer, const CLSID
return E_FAIL;
}
-static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface)
-{
- TransformFilter *filter = impl_from_sink_IPin(iface);
-
- TRACE("iface %p.\n", iface);
-
- if (filter->source.pin.peer)
- return IPin_EndOfStream(filter->source.pin.peer);
- return VFW_E_NOT_CONNECTED;
-}
-
-static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface)
-{
- TransformFilter *pTransform = impl_from_sink_IPin(iface);
- HRESULT hr = S_OK;
-
- TRACE("(%p)->()\n", iface);
-
- EnterCriticalSection(&pTransform->filter.csFilter);
- if (pTransform->pFuncsTable->pfnBeginFlush)
- hr = pTransform->pFuncsTable->pfnBeginFlush(pTransform);
- if (SUCCEEDED(hr))
- hr = BaseInputPinImpl_BeginFlush(iface);
- LeaveCriticalSection(&pTransform->filter.csFilter);
- return hr;
-}
-
-static HRESULT WINAPI TransformFilter_InputPin_EndFlush(IPin * iface)
-{
- TransformFilter *pTransform = impl_from_sink_IPin(iface);
- HRESULT hr = S_OK;
-
- TRACE("(%p)->()\n", iface);
-
- EnterCriticalSection(&pTransform->filter.csFilter);
- if (pTransform->pFuncsTable->pfnEndFlush)
- hr = pTransform->pFuncsTable->pfnEndFlush(pTransform);
- if (SUCCEEDED(hr))
- hr = BaseInputPinImpl_EndFlush(iface);
- LeaveCriticalSection(&pTransform->filter.csFilter);
- return hr;
-}
-
-static HRESULT WINAPI TransformFilter_InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
-{
- TransformFilter *pTransform = impl_from_sink_IPin(iface);
- HRESULT hr = S_OK;
-
- TRACE("iface %p, start %s, stop %s, rate %.16e.\n",
- iface, debugstr_time(tStart), debugstr_time(tStop), dRate);
-
- if (pTransform->pFuncsTable->pfnNewSegment)
- hr = pTransform->pFuncsTable->pfnNewSegment(pTransform, tStart, tStop, dRate);
- if (SUCCEEDED(hr))
- hr = BaseInputPinImpl_NewSegment(iface, tStart, tStop, dRate);
- return hr;
-}
-
static const IPinVtbl TransformFilter_InputPin_Vtbl =
{
BasePinImpl_QueryInterface,
@@ -479,8 +475,8 @@ static const IPinVtbl TransformFilter_InputPin_Vtbl =
BasePinImpl_QueryAccept,
BasePinImpl_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
- TransformFilter_InputPin_EndOfStream,
- TransformFilter_InputPin_BeginFlush,
- TransformFilter_InputPin_EndFlush,
- TransformFilter_InputPin_NewSegment
+ BaseInputPinImpl_EndOfStream,
+ BaseInputPinImpl_BeginFlush,
+ BaseInputPinImpl_EndFlush,
+ BaseInputPinImpl_NewSegment
};
--
2.24.0
Dec. 12, 2019
[PATCH v2 3/8] strmbase: Introduce callbacks for streaming events.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/strmbase/pin.c | 12 ++++++++++++
include/wine/strmbase.h | 4 ++++
2 files changed, 16 insertions(+)
diff --git a/dlls/strmbase/pin.c b/dlls/strmbase/pin.c
index 3dd00b27ccc..f36e147b849 100644
--- a/dlls/strmbase/pin.c
+++ b/dlls/strmbase/pin.c
@@ -718,6 +718,9 @@ HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface)
TRACE("(%p)->()\n", This);
+ if (This->pFuncsTable->sink_eos)
+ return This->pFuncsTable->sink_eos(This);
+
EnterCriticalSection(&This->pin.filter->csFilter);
if (This->flushing)
hr = S_FALSE;
@@ -739,6 +742,9 @@ HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface)
HRESULT hr;
TRACE("(%p) semi-stub\n", This);
+ if (This->pFuncsTable->sink_begin_flush)
+ return This->pFuncsTable->sink_begin_flush(This);
+
EnterCriticalSection(&This->pin.filter->csFilter);
This->flushing = TRUE;
@@ -759,6 +765,9 @@ HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface)
HRESULT hr;
TRACE("(%p)->()\n", This);
+ if (This->pFuncsTable->sink_begin_flush)
+ return This->pFuncsTable->sink_end_flush(This);
+
EnterCriticalSection(&This->pin.filter->csFilter);
This->flushing = FALSE;
@@ -788,6 +797,9 @@ HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME start, R
TRACE("iface %p, start %s, stop %s, rate %.16e.\n",
iface, debugstr_time(start), debugstr_time(stop), rate);
+ if (pin->pFuncsTable->sink_new_segment)
+ return pin->pFuncsTable->sink_new_segment(pin, start, stop, rate);
+
args.tStart = start;
args.tStop = stop;
args.rate = rate;
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index 83ad2e0bd6e..c01ef6133f4 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -95,6 +95,10 @@ struct strmbase_sink_ops
BaseInputPin_Receive pfnReceive;
HRESULT (*sink_connect)(struct strmbase_sink *pin, IPin *peer, const AM_MEDIA_TYPE *mt);
void (*sink_disconnect)(struct strmbase_sink *pin);
+ HRESULT (*sink_eos)(struct strmbase_sink *pin);
+ HRESULT (*sink_begin_flush)(struct strmbase_sink *pin);
+ HRESULT (*sink_end_flush)(struct strmbase_sink *pin);
+ HRESULT (*sink_new_segment)(struct strmbase_sink *pin, REFERENCE_TIME start, REFERENCE_TIME stop, double rate);
};
/* Base Pin */
--
2.24.0
Dec. 12, 2019
[PATCH v2 2/8] wineqtdecoder: Use base sink connection methods.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
v2: fix numerous compilation errors, thanks Alistair.
dlls/wineqtdecoder/qtsplitter.c | 206 ++++++++++++--------------------
1 file changed, 75 insertions(+), 131 deletions(-)
diff --git a/dlls/wineqtdecoder/qtsplitter.c b/dlls/wineqtdecoder/qtsplitter.c
index c8a34cbf95e..01ec4c2cede 100644
--- a/dlls/wineqtdecoder/qtsplitter.c
+++ b/dlls/wineqtdecoder/qtsplitter.c
@@ -228,7 +228,6 @@ static struct strmbase_pin *qt_splitter_get_pin(struct strmbase_filter *base, un
static void qt_splitter_destroy(struct strmbase_filter *iface)
{
QTSplitter *filter = impl_from_strmbase_filter(iface);
- IPin *peer = NULL;
EnterCriticalSection(&filter->csReceive);
/* Don't need to clean up output pins, disconnecting input pin will do that */
@@ -285,13 +284,15 @@ static HRESULT qt_splitter_start_stream(struct strmbase_filter *iface, REFERENCE
EnterCriticalSection(&filter->csReceive);
if (filter->pVideo_Pin)
- pin_hr = BaseOutputPinImpl_Active(&filter->pVideo_Pin->pin);
- if (SUCCEEDED(pin_hr))
- hr = pin_hr;
+ {
+ if (SUCCEEDED(pin_hr = BaseOutputPinImpl_Active(&filter->pVideo_Pin->pin)))
+ hr = pin_hr;
+ }
if (filter->pAudio_Pin)
- pin_hr = BaseOutputPinImpl_Active(&filter->pAudio_Pin->pin);
- if (SUCCEEDED(pin_hr))
- hr = pin_hr;
+ {
+ if (SUCCEEDED(pin_hr = BaseOutputPinImpl_Active(&filter->pAudio_Pin->pin)))
+ hr = pin_hr;
+ }
SetEvent(filter->runEvent);
LeaveCriticalSection(&filter->csReceive);
@@ -331,10 +332,75 @@ static HRESULT sink_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE
return S_FALSE;
}
+static HRESULT QT_Process_Movie(QTSplitter *filter);
+
+static HRESULT qt_splitter_sink_connect(struct strmbase_sink *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ QTSplitter *filter = impl_from_strmbase_filter(iface->pin.filter);
+ ALLOCATOR_PROPERTIES props;
+ IMemAllocator *allocator;
+ HRESULT hr = S_OK;
+
+ filter->pInputPin.pReader = NULL;
+
+ if (FAILED(hr = IPin_QueryInterface(peer, &IID_IAsyncReader, (void **)&filter->pInputPin.pReader)))
+ return hr;
+
+ if (FAILED(hr = QT_Process_Movie(filter)))
+ {
+ IAsyncReader_Release(filter->pInputPin.pReader);
+ filter->pInputPin.pReader = NULL;
+ return hr;
+ }
+
+ filter->pInputPin.pAlloc = NULL;
+ props.cBuffers = 8;
+ props.cbAlign = 1;
+ props.cbBuffer = filter->outputSize + props.cbAlign;
+ props.cbPrefix = 0;
+
+ /* Some applications depend on IAsyncReader::RequestAllocator() passing a
+ * non-NULL preferred allocator. */
+ hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC,
+ &IID_IMemAllocator, (void **)&allocator);
+ if (FAILED(hr))
+ goto err;
+
+ hr = IAsyncReader_RequestAllocator(filter->pInputPin.pReader, allocator, &props, &filter->pInputPin.pAlloc);
+ IMemAllocator_Release(allocator);
+ if (FAILED(hr))
+ {
+ WARN("Failed to get allocator, hr %#x.\n", hr);
+ goto err;
+ }
+
+ if (FAILED(hr = IMemAllocator_Commit(filter->pInputPin.pAlloc)))
+ {
+ WARN("Failed to commit allocator, hr %#x.\n", hr);
+ goto err;
+ }
+
+ return S_OK;
+err:
+ QT_RemoveOutputPins(filter);
+ IAsyncReader_Release(filter->pInputPin.pReader);
+ return hr;
+}
+
+static void qt_splitter_sink_disconnect(struct strmbase_sink *iface)
+{
+ QTSplitter *filter = impl_from_strmbase_filter(iface->pin.filter);
+
+ IMemAllocator_Decommit(filter->pInputPin.pAlloc);
+ QT_RemoveOutputPins(filter);
+}
+
static const struct strmbase_sink_ops sink_ops =
{
.base.pin_query_accept = sink_query_accept,
.base.pin_get_media_type = strmbase_pin_get_media_type,
+ .sink_connect = qt_splitter_sink_connect,
+ .sink_disconnect = qt_splitter_sink_disconnect,
};
IUnknown * CALLBACK QTSplitter_create(IUnknown *outer, HRESULT *phr)
@@ -964,128 +1030,6 @@ static HRESULT QT_Process_Movie(QTSplitter* filter)
return hr;
}
-static HRESULT WINAPI QTInPin_ReceiveConnection(IPin *iface, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
-{
- HRESULT hr = S_OK;
- ALLOCATOR_PROPERTIES props;
- QTInPin *This = impl_from_IPin(iface);
- QTSplitter *filter = impl_from_strmbase_filter(This->pin.filter);
- IMemAllocator *pAlloc;
-
- TRACE("(%p/%p)->(%p, %p)\n", This, iface, pReceivePin, pmt);
-
- EnterCriticalSection(&filter->filter.csFilter);
- This->pReader = NULL;
-
- if (This->pin.pin.peer)
- hr = VFW_E_ALREADY_CONNECTED;
- else if (IPin_QueryAccept(iface, pmt) != S_OK)
- hr = VFW_E_TYPE_NOT_ACCEPTED;
- else
- {
- PIN_DIRECTION pindirReceive;
- IPin_QueryDirection(pReceivePin, &pindirReceive);
- if (pindirReceive != PINDIR_OUTPUT)
- hr = VFW_E_INVALID_DIRECTION;
- }
-
- if (FAILED(hr))
- {
- LeaveCriticalSection(&filter->filter.csFilter);
- return hr;
- }
-
- hr = IPin_QueryInterface(pReceivePin, &IID_IAsyncReader, (LPVOID *)&This->pReader);
- if (FAILED(hr))
- {
- LeaveCriticalSection(&filter->filter.csFilter);
- TRACE("Input source is not an AsyncReader\n");
- return hr;
- }
-
- LeaveCriticalSection(&filter->filter.csFilter);
- EnterCriticalSection(&filter->filter.csFilter);
- hr = QT_Process_Movie(filter);
- if (FAILED(hr))
- {
- IAsyncReader_Release(This->pReader);
- This->pReader = NULL;
- LeaveCriticalSection(&filter->filter.csFilter);
- TRACE("Unable to process movie\n");
- return hr;
- }
-
- This->pAlloc = NULL;
- props.cBuffers = 8;
- props.cbAlign = 1;
- props.cbBuffer = filter->outputSize + props.cbAlign;
- props.cbPrefix = 0;
- hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC,
- &IID_IMemAllocator, (LPVOID *)&pAlloc);
- if (SUCCEEDED(hr))
- {
- /* A certain IAsyncReader::RequestAllocator expects to be passed
- non-NULL preferred allocator */
- hr = IAsyncReader_RequestAllocator(This->pReader, pAlloc, &props, &This->pAlloc);
- if (FAILED(hr))
- WARN("Can't get an allocator, got %08x\n", hr);
- IMemAllocator_Release(pAlloc);
- }
-
- if (SUCCEEDED(hr))
- {
- CopyMediaType(&This->pin.mt, pmt);
- This->pin.peer = pReceivePin;
- IPin_AddRef(pReceivePin);
- hr = IMemAllocator_Commit(This->pAlloc);
- }
- else
- {
- QT_RemoveOutputPins(filter);
- if (This->pReader)
- IAsyncReader_Release(This->pReader);
- This->pReader = NULL;
- if (This->pAlloc)
- IMemAllocator_Release(This->pAlloc);
- This->pAlloc = NULL;
- }
- TRACE("Size: %i\n", props.cbBuffer);
- LeaveCriticalSection(&filter->filter.csFilter);
-
- return hr;
-}
-
-static HRESULT WINAPI QTInPin_Disconnect(IPin *iface)
-{
- HRESULT hr;
- QTInPin *This = impl_from_IPin(iface);
- QTSplitter *filter = impl_from_strmbase_filter(This->pin.pin.filter);
- FILTER_STATE state;
- TRACE("()\n");
-
- hr = IBaseFilter_GetState(&filter->filter.IBaseFilter_iface, INFINITE, &state);
- EnterCriticalSection(&filter->filter.csFilter);
- if (This->pin.pin.peer)
- {
- QTSplitter *Parser = impl_from_strmbase_filter(This->pin.pin.filter);
-
- if (SUCCEEDED(hr) && state == State_Stopped)
- {
- IMemAllocator_Decommit(This->pAlloc);
- IPin_Disconnect(This->pin.pin.peer);
- IPin_Release(This->pin.pin.peer);
- This->pin.pin.peer = NULL;
- hr = QT_RemoveOutputPins(Parser);
- }
- else
- hr = VFW_E_NOT_STOPPED;
- }
- else
- hr = S_FALSE;
- LeaveCriticalSection(&filter->filter.csFilter);
- return hr;
-}
-
static HRESULT WINAPI QTInPin_EndOfStream(IPin *iface)
{
FIXME("iface %p, stub!\n", iface);
@@ -1116,8 +1060,8 @@ static const IPinVtbl QT_InputPin_Vtbl = {
BasePinImpl_AddRef,
BasePinImpl_Release,
BaseInputPinImpl_Connect,
- QTInPin_ReceiveConnection,
- QTInPin_Disconnect,
+ BaseInputPinImpl_ReceiveConnection,
+ BaseInputPinImpl_Disconnect,
BasePinImpl_ConnectedTo,
BasePinImpl_ConnectionMediaType,
BasePinImpl_QueryPinInfo,
--
2.24.0
Dec. 12, 2019
[PATCH v2 1/8] wineqtdecoder: Store the sink as a strmbase_sink structure.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/wineqtdecoder/qtsplitter.c | 43 ++++++++++++++-------------------
1 file changed, 18 insertions(+), 25 deletions(-)
diff --git a/dlls/wineqtdecoder/qtsplitter.c b/dlls/wineqtdecoder/qtsplitter.c
index d861110f5f1..c8a34cbf95e 100644
--- a/dlls/wineqtdecoder/qtsplitter.c
+++ b/dlls/wineqtdecoder/qtsplitter.c
@@ -138,7 +138,7 @@ typedef struct QTOutPin {
} QTOutPin;
typedef struct QTInPin {
- struct strmbase_pin pin;
+ struct strmbase_sink pin;
GUID subType;
IAsyncReader *pReader;
@@ -199,7 +199,7 @@ static inline QTSplitter *impl_from_IBaseFilter( IBaseFilter *iface )
static inline QTInPin *impl_from_IPin(IPin *iface)
{
- return CONTAINING_RECORD(iface, QTInPin, pin.IPin_iface);
+ return CONTAINING_RECORD(iface, QTInPin, pin.pin.IPin_iface);
}
/*
@@ -211,7 +211,7 @@ static struct strmbase_pin *qt_splitter_get_pin(struct strmbase_filter *base, un
QTSplitter *filter = impl_from_strmbase_filter(base);
if (index == 0)
- return &filter->pInputPin.pin;
+ return &filter->pInputPin.pin.pin;
else if (index == 1)
{
if (filter->pVideo_Pin)
@@ -232,18 +232,15 @@ static void qt_splitter_destroy(struct strmbase_filter *iface)
EnterCriticalSection(&filter->csReceive);
/* Don't need to clean up output pins, disconnecting input pin will do that */
+ if (filter->pInputPin.pin.pin.peer)
+ IPin_Disconnect(filter->pInputPin.pin.pin.peer);
- if (filter->pInputPin.pin.peer)
- IPin_Disconnect(filter->pInputPin.pin.peer);
-
- FreeMediaType(&filter->pInputPin.pin.mt);
if (filter->pInputPin.pAlloc)
IMemAllocator_Release(filter->pInputPin.pAlloc);
filter->pInputPin.pAlloc = NULL;
if (filter->pInputPin.pReader)
IAsyncReader_Release(filter->pInputPin.pReader);
filter->pInputPin.pReader = NULL;
- filter->pInputPin.pin.IPin_iface.lpVtbl = NULL;
if (filter->pQTMovie)
{
@@ -274,6 +271,7 @@ static void qt_splitter_destroy(struct strmbase_filter *iface)
filter->csReceive.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&filter->csReceive);
+ strmbase_sink_cleanup(&filter->pInputPin.pin);
strmbase_filter_cleanup(&filter->filter);
CoTaskMemFree(filter);
@@ -333,10 +331,10 @@ static HRESULT sink_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE
return S_FALSE;
}
-static const BasePinFuncTable sink_ops =
+static const struct strmbase_sink_ops sink_ops =
{
- .pin_query_accept = sink_query_accept,
- .pin_get_media_type = strmbase_pin_get_media_type,
+ .base.pin_query_accept = sink_query_accept,
+ .base.pin_get_media_type = strmbase_pin_get_media_type,
};
IUnknown * CALLBACK QTSplitter_create(IUnknown *outer, HRESULT *phr)
@@ -357,6 +355,8 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *outer, HRESULT *phr)
ZeroMemory(This,sizeof(*This));
strmbase_filter_init(&This->filter, outer, &CLSID_QTSplitter, &filter_ops);
+ strmbase_sink_init(&This->pInputPin.pin, &QT_InputPin_Vtbl, &This->filter,
+ wcsInputPinName, &sink_ops, NULL);
InitializeCriticalSection(&This->csReceive);
This->csReceive.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": QTSplitter.csReceive");
@@ -366,13 +366,6 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *outer, HRESULT *phr)
This->aSession = NULL;
This->runEvent = CreateEventW(NULL, 0, 0, NULL);
- This->pInputPin.pin.dir = PINDIR_INPUT;
- This->pInputPin.pin.filter = &This->filter;
- lstrcpynW(This->pInputPin.pin.name, wcsInputPinName, ARRAY_SIZE(This->pInputPin.pin.name));
- This->pInputPin.pin.IPin_iface.lpVtbl = &QT_InputPin_Vtbl;
- This->pInputPin.pin.peer = NULL;
- This->pInputPin.pin.pFuncsTable = &sink_ops;
-
*phr = S_OK;
return &This->filter.IUnknown_inner;
}
@@ -984,7 +977,7 @@ static HRESULT WINAPI QTInPin_ReceiveConnection(IPin *iface, IPin *pReceivePin,
EnterCriticalSection(&filter->filter.csFilter);
This->pReader = NULL;
- if (This->pin.peer)
+ if (This->pin.pin.peer)
hr = VFW_E_ALREADY_CONNECTED;
else if (IPin_QueryAccept(iface, pmt) != S_OK)
hr = VFW_E_TYPE_NOT_ACCEPTED;
@@ -1066,22 +1059,22 @@ static HRESULT WINAPI QTInPin_Disconnect(IPin *iface)
{
HRESULT hr;
QTInPin *This = impl_from_IPin(iface);
- QTSplitter *filter = impl_from_strmbase_filter(This->pin.filter);
+ QTSplitter *filter = impl_from_strmbase_filter(This->pin.pin.filter);
FILTER_STATE state;
TRACE("()\n");
hr = IBaseFilter_GetState(&filter->filter.IBaseFilter_iface, INFINITE, &state);
EnterCriticalSection(&filter->filter.csFilter);
- if (This->pin.peer)
+ if (This->pin.pin.peer)
{
- QTSplitter *Parser = impl_from_strmbase_filter(This->pin.filter);
+ QTSplitter *Parser = impl_from_strmbase_filter(This->pin.pin.filter);
if (SUCCEEDED(hr) && state == State_Stopped)
{
IMemAllocator_Decommit(This->pAlloc);
- IPin_Disconnect(This->pin.peer);
- IPin_Release(This->pin.peer);
- This->pin.peer = NULL;
+ IPin_Disconnect(This->pin.pin.peer);
+ IPin_Release(This->pin.pin.peer);
+ This->pin.pin.peer = NULL;
hr = QT_RemoveOutputPins(Parser);
}
else
--
2.24.0
Dec. 12, 2019
Re: [PATCH v4 1/9] jscript: Store the necessary function and variable info in the TypeInfo.
by Francois Gouget
On Thu, 12 Dec 2019, Francois Gouget wrote:
> On Thu, 12 Dec 2019, Gabriel Ivăncescu wrote:
>
> > Was the testbot not synced with wine master? The bytecode field patch should
> > have been committed yesterday, AFAIK.
>
> Yes. The change in the wine-gecko package name broke the update.
> I sent a patch to fix this and I'm going to manually update the debian
> VM shortly.
Done.
--
Francois Gouget <fgouget(a)codeweavers.com>
Dec. 12, 2019
Re: [PATCH v2 3/5] d3d9: Handle multisample depth resolve in d3d9_device_SetRenderState().
by Henri Verbeet
On Wed, 11 Dec 2019 at 07:16, Zebediah Figura <z.figura12(a)gmail.com> wrote:
> @@ -289,8 +289,18 @@ static HRESULT WINAPI d3d9_CheckDeviceFormat(IDirect3D9Ex *iface, UINT adapter,
> }
>
> wined3d_mutex_lock();
> - hr = wined3d_check_device_format(d3d9->wined3d, adapter, device_type, wined3dformat_from_d3dformat(adapter_format),
> - usage, bind_flags, wined3d_rtype, wined3dformat_from_d3dformat(format));
> + if ((enum wined3d_format_id)format == WINED3DFMT_RESZ)
> + {
> + DWORD levels;
> + hr = wined3d_check_device_multisample_type(d3d9->wined3d, adapter, device_type,
> + WINED3DFMT_D24_UNORM_S8_UINT, FALSE, WINED3D_MULTISAMPLE_NONE, &levels);
Did you intend to use WINED3D_MULTISAMPLE_NON_MASKABLE here?
It seems a little superfluous to export
wined3d_device_resolve_depth_buffer(); the implementation on top of
wined3d_device_resolve_sub_resource() wasn't that complicated.
Dec. 12, 2019
[PATCH 4/4] msvcrt: Implement sequential and random mode flags.
by Akihiro Sagawa
Signed-off-by: Akihiro Sagawa <sagawa.aki(a)gmail.com>
---
dlls/msvcrt/file.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
Dec. 12, 2019
[PATCH 3/4] msvcrt: Implement _O_RANDOM and _O_SEQUENTIAL flags.
by Akihiro Sagawa
Signed-off-by: Akihiro Sagawa <sagawa.aki(a)gmail.com>
---
dlls/msvcrt/file.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
Dec. 12, 2019
[PATCH 2/4] kernelbase: Implement FILE_FLAG_SEQUENTIAL_SCAN.
by Akihiro Sagawa
Signed-off-by: Akihiro Sagawa <sagawa.aki(a)gmail.com>
---
dlls/kernel32/tests/file.c | 16 ++++++++++++++++
dlls/kernelbase/file.c | 2 ++
2 files changed, 18 insertions(+)
Dec. 12, 2019
[PATCH 1/4] server: Implement access pattern hints for file data.
by Akihiro Sagawa
Signed-off-by: Akihiro Sagawa <sagawa.aki(a)gmail.com>
---
configure | 1 +
configure.ac | 1 +
dlls/ntdll/tests/file.c | 2 ++
include/config.h.in | 3 +++
server/fd.c | 19 +++++++++++++++++++
5 files changed, 26 insertions(+)
Dec. 12, 2019
Re: [PATCH v4 1/9] jscript: Store the necessary function and variable info in the TypeInfo.
by Francois Gouget
On Thu, 12 Dec 2019, Gabriel Ivăncescu wrote:
> Was the testbot not synced with wine master? The bytecode field patch should
> have been committed yesterday, AFAIK.
Yes. The change in the wine-gecko package name broke the update.
I sent a patch to fix this and I'm going to manually update the debian
VM shortly.
--
Francois Gouget <fgouget(a)codeweavers.com>
Dec. 12, 2019
Re: [PATCH v4 9/9] jscript/tests: Add initial tests for the script TypeInfo.
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=62031
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1241:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1241:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
Re: [PATCH v4 8/9] jscript: Implement ScriptTypeComp_BindType.
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=62030
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1241:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1241:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
Re: [PATCH v2 1/5] wined3d: Introduce wined3d_device_apply_stateblock().
by Henri Verbeet
On Wed, 11 Dec 2019 at 07:16, Zebediah Figura <z.figura12(a)gmail.com> wrote:
> + wined3d_device_set_vs_consts_f(device, 0, d3d_info->limits.vs_uniform_count, state->vs_consts_f);
> + wined3d_device_set_vs_consts_b(device, 0, WINED3D_MAX_CONSTS_B, state->vs_consts_b);
> + wined3d_device_set_vs_consts_i(device, 0, WINED3D_MAX_CONSTS_I, state->vs_consts_i);
> + wined3d_device_set_ps_consts_f(device, 0, d3d_info->limits.ps_uniform_count, state->ps_consts_f);
> + wined3d_device_set_ps_consts_b(device, 0, WINED3D_MAX_CONSTS_B, state->ps_consts_b);
> + wined3d_device_set_ps_consts_i(device, 0, WINED3D_MAX_CONSTS_I, state->ps_consts_i);
> +
That's going to invalidate every constant on every draw, even if none
of them changed, which seems undesirable. It shouldn't be too hard to
extract ranges from the "changed" info, although ideally changed float
constants would be stored in a proper bitmap first.
Dec. 12, 2019
Re: [PATCH v4 7/9] jscript: Implement ScriptTypeComp_Bind.
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=62029
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1226:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1226:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
Re: [PATCH v4 6/9] jscript: Implement ScriptTypeInfo_GetTypeComp.
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=62028
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1181:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1181:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
Re: [PATCH v4 1/9] jscript: Store the necessary function and variable info in the TypeInfo.
by Gabriel Ivăncescu
Was the testbot not synced with wine master? The bytecode field patch
should have been committed yesterday, AFAIK.
On 12/12/19 3:01 PM, Marvin wrote:
> 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=62023
>
> Your paranoid android.
>
>
> === debian10 (build log) ===
>
> ../../../wine/dlls/jscript/dispex.c:669:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
> ../../../wine/dlls/jscript/dispex.c:1013:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
> Task: The win32 build failed
>
> === debian10 (build log) ===
>
> ../../../wine/dlls/jscript/dispex.c:669:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
> ../../../wine/dlls/jscript/dispex.c:1013:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
> Task: The wow64 build failed
>
Dec. 12, 2019
Re: [PATCH v4 5/9] jscript: Implement ScriptTypeInfo_GetIDsOfNames.
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=62027
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1121:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1121:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
Re: [PATCH v4 4/9] jscript: Implement ScriptTypeInfo_GetVarDesc.
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=62026
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1078:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1078:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
Re: [PATCH v4 3/9] jscript: Implement ScriptTypeInfo_GetFuncDesc.
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=62025
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1064:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1064:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
Re: [PATCH v4 2/9] jscript: Implement ScriptTypeInfo_GetTypeAttr.
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=62024
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1039:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1039:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
Re: [PATCH v4 1/9] jscript: Store the necessary function and variable info in the TypeInfo.
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=62023
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:669:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1013:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:669:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
../../../wine/dlls/jscript/dispex.c:1013:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’
Task: The wow64 build failed
Dec. 12, 2019
[PATCH v4 9/9] jscript/tests: Add initial tests for the script TypeInfo.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/tests/jscript.c | 362 +++++++++++++++++++++++++++++++++++
1 file changed, 362 insertions(+)
diff --git a/dlls/jscript/tests/jscript.c b/dlls/jscript/tests/jscript.c
index 0904374..e608367 100644
--- a/dlls/jscript/tests/jscript.c
+++ b/dlls/jscript/tests/jscript.c
@@ -33,6 +33,8 @@
#define IActiveScriptParse_Release IActiveScriptParse64_Release
#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
+#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_64_Release
+#define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_64_ParseProcedureText
#else
@@ -40,10 +42,13 @@
#define IActiveScriptParse_Release IActiveScriptParse32_Release
#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
+#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_32_Release
+#define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_32_ParseProcedureText
#endif
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+DEFINE_GUID(IID_IScriptTypeInfo, 0xc59c6b12, 0xf6c1, 0x11cf, 0x88,0x35, 0x00,0xa0,0xc9,0x11,0xe8,0xb2);
static const CLSID CLSID_JScript =
{0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}};
@@ -274,6 +279,20 @@ static IDispatchEx *get_script_dispatch(IActiveScript *script)
return dispex;
}
+static void parse_script(IActiveScriptParse *parser, const WCHAR *src)
+{
+ HRESULT hres;
+
+ SET_EXPECT(OnEnterScript);
+ SET_EXPECT(OnLeaveScript);
+
+ hres = IActiveScriptParse_ParseScriptText(parser, src, NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
+ ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
+
+ CHECK_CALLED(OnEnterScript);
+ CHECK_CALLED(OnLeaveScript);
+}
+
#define get_disp_id(a,b,c,d) _get_disp_id(__LINE__,a,b,c,d)
static void _get_disp_id(unsigned line, IDispatchEx *dispex, const WCHAR *name, HRESULT exhr, DISPID *id)
{
@@ -907,6 +926,347 @@ static void test_code_persistence(void)
CHECK_CALLED(OnStateChange_CLOSED);
}
+static void test_typeinfo(const WCHAR *parse_func_name)
+{
+ static struct
+ {
+ const WCHAR *name;
+ UINT num_args;
+ } func[] =
+ {
+ { L"emptyfn", 0 },
+ { L"voidfn", 0 },
+ { L"math", 2 },
+ { L"foobar", 1 },
+ { L"C", 0 },
+ { L"funcvar", 2 },
+ { L"f1", 1 },
+ { L"f2", 1 }
+ };
+ static struct
+ {
+ const WCHAR *name;
+ } var[] =
+ {
+ { L"global_var" },
+ { L"uninit" },
+ { L"obj" }
+ };
+ const WCHAR *source = L""
+ "var global_var = 42;\n"
+
+ "function emptyfn() { }\n"
+ "function voidfn() { return void(0); }\n"
+ "function math(x, y) { return x - y; }\n"
+ "function foobar(x) { return \"foobar\"; }\n"
+
+ "function C() {\n"
+ " this.x;\n"
+ " this.strret = function() { return \"ret\"; }\n"
+ "}\n"
+
+ "var uninit;\n"
+ "var obj = new C();\n"
+
+ "var funcvar = function(x, y) { return x * y; };\n"
+ "var native_func = decodeURI;\n"
+
+ "(function() {\n"
+ " f1 = function infuncexpr(x) { return 1; }\n"
+ " f2 = function infuncexpr(x) { return 2; }\n"
+ "})();\n";
+ UINT expected_funcs_cnt = parse_func_name ? 0 : ARRAY_SIZE(func);
+ UINT expected_vars_cnt = parse_func_name ? 0 : ARRAY_SIZE(var);
+
+ ITypeInfo *typeinfo, *typeinfo2;
+ ITypeComp *typecomp, *typecomp2;
+ IActiveScriptParse *parser;
+ IActiveScript *script;
+ FUNCDESC *funcdesc;
+ VARDESC *vardesc;
+ IDispatchEx *disp;
+ DESCKIND desckind;
+ BINDPTR bindptr;
+ MEMBERID memid;
+ TYPEATTR *attr;
+ UINT index;
+ HRESULT hr;
+ WCHAR str[64], *names = str;
+ int i;
+
+ if (parse_func_name)
+ trace("Testing TypeInfo for function %s...\n", wine_dbgstr_w(parse_func_name));
+ else
+ trace("Testing TypeInfo for script dispatch...\n");
+
+ script = create_jscript();
+
+ hr = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser);
+ ok(hr == S_OK, "Could not get IActiveScriptParse iface: %08x\n", hr);
+
+ SET_EXPECT(GetLCID);
+ hr = IActiveScript_SetScriptSite(script, &ActiveScriptSite);
+ ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr);
+ CHECK_CALLED(GetLCID);
+
+ SET_EXPECT(OnStateChange_INITIALIZED);
+ hr = IActiveScriptParse_InitNew(parser);
+ ok(hr == S_OK, "InitNew failed: %08x\n", hr);
+ CHECK_CALLED(OnStateChange_INITIALIZED);
+
+ SET_EXPECT(OnStateChange_CONNECTED);
+ hr = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED);
+ ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hr);
+ CHECK_CALLED(OnStateChange_CONNECTED);
+
+ if (parse_func_name)
+ {
+ IActiveScriptParseProcedure2 *parse_proc;
+ IDispatch *proc_disp;
+
+ hr = IActiveScript_QueryInterface(script, &IID_IActiveScriptParseProcedure2, (void**)&parse_proc);
+ ok(hr == S_OK, "Could not get IActiveScriptParse: %08x\n", hr);
+
+ hr = IActiveScriptParseProcedure2_ParseProcedureText(parse_proc, source, NULL, parse_func_name,
+ NULL, NULL, NULL, 0, 0, SCRIPTPROC_IMPLICIT_THIS | SCRIPTPROC_IMPLICIT_PARENTS, &proc_disp);
+ ok(hr == S_OK, "ParseProcedureText failed: %08x\n", hr);
+ IActiveScriptParseProcedure2_Release(parse_proc);
+
+ hr = IDispatch_QueryInterface(proc_disp, &IID_IDispatchEx, (void**)&disp);
+ ok(hr == S_OK, "Could not get IDispatchEx: %08x\n", hr);
+ IDispatch_Release(proc_disp);
+ }
+ else
+ {
+ parse_script(parser, source);
+ disp = get_script_dispatch(script);
+ }
+
+ hr = IDispatchEx_QueryInterface(disp, &IID_ITypeInfo, (void**)&typeinfo);
+ ok(hr == E_NOINTERFACE, "QueryInterface(IID_ITypeInfo) returned: %08x\n", hr);
+ hr = IDispatchEx_GetTypeInfo(disp, 1, LOCALE_USER_DEFAULT, &typeinfo);
+ ok(hr == DISP_E_BADINDEX, "GetTypeInfo returned: %08x\n", hr);
+ hr = IDispatchEx_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &typeinfo);
+ ok(hr == S_OK, "GetTypeInfo failed: %08x\n", hr);
+ hr = IDispatchEx_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &typeinfo2);
+ ok(hr == S_OK, "GetTypeInfo failed: %08x\n", hr);
+ ok(typeinfo != typeinfo2, "TypeInfo was not supposed to be shared.\n");
+ ITypeInfo_Release(typeinfo2);
+
+ hr = ITypeInfo_GetTypeAttr(typeinfo, &attr);
+ ok(hr == S_OK, "GetTypeAttr failed: %08x\n", hr);
+ ok(IsEqualGUID(&attr->guid, &IID_IScriptTypeInfo), "Unexpected GUID %s\n", wine_dbgstr_guid(&attr->guid));
+ ok(attr->lcid == LOCALE_USER_DEFAULT, "Unexpected LCID %u\n", attr->lcid);
+ ok(attr->memidConstructor == MEMBERID_NIL, "Unexpected constructor memid %u\n", attr->memidConstructor);
+ ok(attr->memidDestructor == MEMBERID_NIL, "Unexpected destructor memid %u\n", attr->memidDestructor);
+ ok(attr->cbSizeInstance == 4, "Unexpected cbSizeInstance %u\n", attr->cbSizeInstance);
+ ok(attr->typekind == TKIND_DISPATCH, "Unexpected typekind %u\n", attr->typekind);
+ ok(attr->cFuncs == expected_funcs_cnt, "Unexpected cFuncs %u\n", attr->cFuncs);
+ ok(attr->cVars == expected_vars_cnt, "Unexpected cVars %u\n", attr->cVars);
+ ok(attr->cImplTypes == 1, "Unexpected cImplTypes %u\n", attr->cImplTypes);
+ ok(attr->cbSizeVft == sizeof(IDispatchVtbl), "Unexpected cbSizeVft %u\n", attr->cbSizeVft);
+ ok(attr->cbAlignment == 4, "Unexpected cbAlignment %u\n", attr->cbAlignment);
+ ok(attr->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "Unexpected wTypeFlags 0x%x\n", attr->wTypeFlags);
+ ok(attr->tdescAlias.vt == VT_EMPTY, "Unexpected tdescAlias.vt %d\n", attr->tdescAlias.vt);
+ ok(attr->idldescType.wIDLFlags == IDLFLAG_NONE, "Unexpected idldescType.wIDLFlags 0x%x\n", attr->idldescType.wIDLFlags);
+ ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
+
+ /* GetIDsOfNames looks into the inherited types as well */
+ wcscpy(str, L"queryinterface");
+ hr = ITypeInfo_GetIDsOfNames(typeinfo, NULL, 1, &memid);
+ ok(hr == E_INVALIDARG, "GetIDsOfNames returned: %08x\n", hr);
+ hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 1, NULL);
+ ok(hr == E_INVALIDARG, "GetIDsOfNames returned: %08x\n", hr);
+ hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 0, &memid);
+ ok(hr == E_INVALIDARG, "GetIDsOfNames returned: %08x\n", hr);
+ hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 1, &memid);
+ ok(hr == S_OK, "GetIDsOfNames failed: %08x\n", hr);
+ ok(!lstrcmpW(str, L"queryinterface"), "Unexpected string %s\n", wine_dbgstr_w(str));
+ if (expected_funcs_cnt)
+ {
+ wcscpy(str, L"Math");
+ hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 1, &memid);
+ ok(hr == S_OK, "GetIDsOfNames failed: %08x\n", hr);
+ ok(!lstrcmpW(str, L"Math"), "Unexpected string %s\n", wine_dbgstr_w(str));
+ }
+
+ /* Check variable descriptions */
+ hr = ITypeInfo_GetVarDesc(typeinfo, 0, NULL);
+ ok(hr == E_INVALIDARG, "GetVarDesc returned: %08x\n", hr);
+ hr = ITypeInfo_GetVarDesc(typeinfo, 1337, &vardesc);
+ ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetVarDesc returned: %08x\n", hr);
+ for (i = 0; i < expected_vars_cnt; i++)
+ {
+ hr = ITypeInfo_GetVarDesc(typeinfo, i, &vardesc);
+ ok(hr == S_OK, "GetVarDesc(%u) failed: %08x\n", i, hr);
+ ok(vardesc->memid <= 0xFFFF, "[%u] Unexpected memid 0x%x\n", i, vardesc->memid);
+ ok(vardesc->lpstrSchema == NULL, "[%u] Unexpected lpstrSchema %p\n", i, vardesc->lpstrSchema);
+ ok(vardesc->oInst == 0, "[%u] Unexpected oInst %u\n", i, vardesc->oInst);
+ ok(vardesc->varkind == VAR_DISPATCH, "[%u] Unexpected varkind %d\n", i, vardesc->varkind);
+ ok(vardesc->wVarFlags == 0, "[%u] Unexpected wVarFlags 0x%x\n", i, vardesc->wVarFlags);
+ ok(vardesc->elemdescVar.tdesc.vt == VT_VARIANT,
+ "[%u] Unexpected variable type vt %d (expected %d)\n", i, vardesc->elemdescVar.tdesc.vt, 0);
+ ok(vardesc->elemdescVar.paramdesc.pparamdescex == NULL,
+ "[%u] Unexpected variable type pparamdescex %p\n", i, vardesc->elemdescVar.paramdesc.pparamdescex);
+ ok(vardesc->elemdescVar.paramdesc.wParamFlags == PARAMFLAG_NONE,
+ "[%u] Unexpected variable type wParamFlags 0x%x\n", i, vardesc->elemdescVar.paramdesc.wParamFlags);
+ ITypeInfo_ReleaseVarDesc(typeinfo, vardesc);
+ }
+
+ /* Check function descriptions */
+ hr = ITypeInfo_GetFuncDesc(typeinfo, 0, NULL);
+ ok(hr == E_INVALIDARG, "GetFuncDesc returned: %08x\n", hr);
+ hr = ITypeInfo_GetFuncDesc(typeinfo, 1337, &funcdesc);
+ ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetFuncDesc returned: %08x\n", hr);
+ for (i = 0; i < expected_funcs_cnt; i++)
+ {
+ hr = ITypeInfo_GetFuncDesc(typeinfo, i, &funcdesc);
+ ok(hr == S_OK, "GetFuncDesc(%u) failed: %08x\n", i, hr);
+ ok(funcdesc->memid <= 0xFFFF, "[%u] Unexpected memid 0x%x\n", i, funcdesc->memid);
+ ok(funcdesc->lprgscode == NULL, "[%u] Unexpected lprgscode %p\n", i, funcdesc->lprgscode);
+ ok(func[i].num_args ? (funcdesc->lprgelemdescParam != NULL) : (funcdesc->lprgelemdescParam == NULL),
+ "[%u] Unexpected lprgelemdescParam %p\n", i, funcdesc->lprgelemdescParam);
+ ok(funcdesc->funckind == FUNC_DISPATCH, "[%u] Unexpected funckind %u\n", i, funcdesc->funckind);
+ ok(funcdesc->invkind == INVOKE_FUNC, "[%u] Unexpected invkind %u\n", i, funcdesc->invkind);
+ ok(funcdesc->callconv == CC_STDCALL, "[%u] Unexpected callconv %u\n", i, funcdesc->callconv);
+ ok(funcdesc->cParams == func[i].num_args, "[%u] Unexpected cParams %d (expected %d)\n",
+ i, funcdesc->cParams, func[i].num_args);
+ ok(funcdesc->cParamsOpt == 0, "[%u] Unexpected cParamsOpt %d\n", i, funcdesc->cParamsOpt);
+ ok(funcdesc->cScodes == 0, "[%u] Unexpected cScodes %d\n", i, funcdesc->cScodes);
+ ok(funcdesc->wFuncFlags == 0, "[%u] Unexpected wFuncFlags 0x%x\n", i, funcdesc->wFuncFlags);
+ ok(funcdesc->elemdescFunc.tdesc.vt == VT_VARIANT,
+ "[%u] Unexpected return type vt %d\n", i, funcdesc->elemdescFunc.tdesc.vt);
+ ok(funcdesc->elemdescFunc.paramdesc.pparamdescex == NULL,
+ "[%u] Unexpected return type pparamdescex %p\n", i, funcdesc->elemdescFunc.paramdesc.pparamdescex);
+ ok(funcdesc->elemdescFunc.paramdesc.wParamFlags == PARAMFLAG_NONE,
+ "[%u] Unexpected return type wParamFlags 0x%x\n", i, funcdesc->elemdescFunc.paramdesc.wParamFlags);
+ if (funcdesc->lprgelemdescParam)
+ for (index = 0; index < funcdesc->cParams; index++)
+ {
+ ok(funcdesc->lprgelemdescParam[index].tdesc.vt == VT_VARIANT,
+ "[%u] Unexpected parameter %u vt %d\n", i, index, funcdesc->lprgelemdescParam[index].tdesc.vt);
+ ok(funcdesc->lprgelemdescParam[index].paramdesc.pparamdescex == NULL,
+ "[%u] Unexpected parameter %u pparamdescex %p\n", i, index, funcdesc->lprgelemdescParam[index].paramdesc.pparamdescex);
+ ok(funcdesc->lprgelemdescParam[index].paramdesc.wParamFlags == PARAMFLAG_NONE,
+ "[%u] Unexpected parameter %u wParamFlags 0x%x\n", i, index, funcdesc->lprgelemdescParam[index].paramdesc.wParamFlags);
+ }
+ ITypeInfo_ReleaseFuncDesc(typeinfo, funcdesc);
+ }
+
+ /* Test TypeComp Binds */
+ hr = ITypeInfo_QueryInterface(typeinfo, &IID_ITypeComp, (void**)&typecomp);
+ ok(hr == S_OK, "QueryInterface(IID_ITypeComp) failed: %08x\n", hr);
+ hr = ITypeInfo_GetTypeComp(typeinfo, NULL);
+ ok(hr == E_INVALIDARG, "GetTypeComp returned: %08x\n", hr);
+ hr = ITypeInfo_GetTypeComp(typeinfo, &typecomp2);
+ ok(hr == S_OK, "GetTypeComp failed: %08x\n", hr);
+ ok(typecomp == typecomp2, "QueryInterface(IID_ITypeComp) and GetTypeComp returned different TypeComps\n");
+ ITypeComp_Release(typecomp2);
+ wcscpy(str, L"not_found");
+ hr = ITypeComp_Bind(typecomp, NULL, 0, 0, &typeinfo2, &desckind, &bindptr);
+ ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr);
+ hr = ITypeComp_Bind(typecomp, str, 0, 0, NULL, &desckind, &bindptr);
+ ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr);
+ hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, NULL, &bindptr);
+ ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr);
+ hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, NULL);
+ ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr);
+ hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, &bindptr);
+ ok(hr == S_OK, "Bind failed: %08x\n", hr);
+ ok(desckind == DESCKIND_NONE, "Unexpected desckind %u\n", desckind);
+ wcscpy(str, L"addRef");
+ hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, &bindptr);
+ ok(hr == S_OK, "Bind failed: %08x\n", hr);
+ ok(desckind == DESCKIND_FUNCDESC, "Unexpected desckind %u\n", desckind);
+ ok(!lstrcmpW(str, L"addRef"), "Unexpected string %s\n", wine_dbgstr_w(str));
+ ITypeInfo_ReleaseFuncDesc(typeinfo2, bindptr.lpfuncdesc);
+ ITypeInfo_Release(typeinfo2);
+ for (i = 0; i < expected_vars_cnt; i++)
+ {
+ wcscpy(str, var[i].name);
+ hr = ITypeComp_Bind(typecomp, str, 0, INVOKE_PROPERTYGET, &typeinfo2, &desckind, &bindptr);
+ ok(hr == S_OK, "Bind failed: %08x\n", hr);
+ ok(desckind == DESCKIND_VARDESC, "Unexpected desckind %u\n", desckind);
+ ITypeInfo_ReleaseVarDesc(typeinfo2, bindptr.lpvardesc);
+ ITypeInfo_Release(typeinfo2);
+ }
+ for (i = 0; i < expected_funcs_cnt; i++)
+ {
+ wcscpy(str, func[i].name);
+ hr = ITypeComp_Bind(typecomp, str, 0, INVOKE_FUNC, &typeinfo2, &desckind, &bindptr);
+ ok(hr == S_OK, "Bind failed: %08x\n", hr);
+ ok(desckind == DESCKIND_FUNCDESC, "Unexpected desckind %u\n", desckind);
+ ITypeInfo_ReleaseFuncDesc(typeinfo2, bindptr.lpfuncdesc);
+ ITypeInfo_Release(typeinfo2);
+ }
+ wcscpy(str, L"JScriptTypeInfo");
+ hr = ITypeComp_BindType(typecomp, NULL, 0, &typeinfo2, &typecomp2);
+ ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr);
+ hr = ITypeComp_BindType(typecomp, str, 0, NULL, &typecomp2);
+ ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr);
+ hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, NULL);
+ ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr);
+ hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2);
+ ok(hr == S_OK, "BindType failed: %08x\n", hr);
+ ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2);
+ ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2);
+ wcscpy(str, L"C");
+ hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2);
+ ok(hr == S_OK, "BindType failed: %08x\n", hr);
+ ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2);
+ ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2);
+ wcscpy(str, L"IDispatch");
+ hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2);
+ ok(hr == S_OK, "BindType failed: %08x\n", hr);
+ ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2);
+ ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2);
+ ITypeComp_Release(typecomp);
+
+ /* Updating the script won't update the typeinfo obtained before,
+ but it will be reflected in any typeinfo obtained afterwards. */
+ if (!parse_func_name)
+ {
+ parse_script(parser, L""
+ "var new_var;\n"
+ "function new_func() { }\n");
+
+ hr = IDispatchEx_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &typeinfo2);
+ ok(hr == S_OK, "GetTypeInfo failed: %08x\n", hr);
+ hr = ITypeInfo_GetTypeAttr(typeinfo, &attr);
+ ok(hr == S_OK, "GetTypeAttr failed: %08x\n", hr);
+ ok(attr->cFuncs == expected_funcs_cnt, "Unexpected cFuncs %u\n", attr->cFuncs);
+ ok(attr->cVars == expected_vars_cnt, "Unexpected cVars %u\n", attr->cVars);
+ ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
+ hr = ITypeInfo_GetTypeAttr(typeinfo2, &attr);
+ ok(hr == S_OK, "GetTypeAttr failed: %08x\n", hr);
+ ok(attr->cFuncs == expected_funcs_cnt + 1, "Unexpected cFuncs %u\n", attr->cFuncs);
+ ok(attr->cVars == expected_vars_cnt + 1, "Unexpected cVars %u\n", attr->cVars);
+ ITypeInfo_ReleaseTypeAttr(typeinfo2, attr);
+ ITypeInfo_Release(typeinfo2);
+
+ /* Adding an identifier that differs only in case gives an error
+ when retrieving the TypeInfo, even though it is valid jscript. */
+ parse_script(parser, L"var NEW_FUNC;\n");
+ hr = IDispatchEx_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &typeinfo2);
+ ok(hr == TYPE_E_AMBIGUOUSNAME, "GetTypeInfo returned: %08x\n", hr);
+ }
+
+ ITypeInfo_Release(typeinfo);
+ IDispatchEx_Release(disp);
+ IActiveScriptParse_Release(parser);
+
+ SET_EXPECT(OnStateChange_DISCONNECTED);
+ SET_EXPECT(OnStateChange_INITIALIZED);
+ SET_EXPECT(OnStateChange_CLOSED);
+ hr = IActiveScript_Close(script);
+ ok(hr == S_OK, "Close failed: %08x\n", hr);
+ CHECK_CALLED(OnStateChange_DISCONNECTED);
+ CHECK_CALLED(OnStateChange_INITIALIZED);
+ CHECK_CALLED(OnStateChange_CLOSED);
+
+ IActiveScript_Release(script);
+}
+
static BOOL check_jscript(void)
{
IActiveScriptProperty *script_prop;
@@ -931,6 +1291,8 @@ START_TEST(jscript)
test_jscript_uninitializing();
test_aggregation();
test_code_persistence();
+ test_typeinfo(NULL);
+ test_typeinfo(L"some_func_name");
trace("Testing JScriptEncode object...\n");
engine_clsid = &CLSID_JScriptEncode;
--
2.21.0
Dec. 12, 2019
[PATCH v4 8/9] jscript: Implement ScriptTypeComp_BindType.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 6576605..6cc6df5 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -1069,10 +1069,25 @@ static HRESULT WINAPI ScriptTypeComp_BindType(ITypeComp *iface, LPOLESTR szName,
ITypeInfo **ppTInfo, ITypeComp **ppTComp)
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface);
+ ITypeInfo *disp_typeinfo;
+ ITypeComp *disp_typecomp;
+ HRESULT hr;
- FIXME("(%p)->(%s %08x %p %p)\n", This, debugstr_w(szName), lHashVal, ppTInfo, ppTComp);
+ TRACE("(%p)->(%s %08x %p %p)\n", This, debugstr_w(szName), lHashVal, ppTInfo, ppTComp);
- return E_NOTIMPL;
+ if (!szName || !ppTInfo || !ppTComp)
+ return E_INVALIDARG;
+
+ /* Look into the inherited IDispatch */
+ hr = get_dispatch_typeinfo(&disp_typeinfo);
+ if (FAILED(hr)) return hr;
+
+ hr = ITypeInfo_GetTypeComp(disp_typeinfo, &disp_typecomp);
+ if (FAILED(hr)) return hr;
+
+ hr = ITypeComp_BindType(disp_typecomp, szName, lHashVal, ppTInfo, ppTComp);
+ ITypeComp_Release(disp_typecomp);
+ return hr;
}
static const ITypeCompVtbl ScriptTypeCompVtbl = {
--
2.21.0
Dec. 12, 2019
[PATCH v4 7/9] jscript: Implement ScriptTypeComp_Bind.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 49 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index fb636b4..6576605 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -1013,11 +1013,56 @@ static HRESULT WINAPI ScriptTypeComp_Bind(ITypeComp *iface, LPOLESTR szName, ULO
ITypeInfo **ppTInfo, DESCKIND *pDescKind, BINDPTR *pBindPtr)
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface);
+ UINT flags = wFlags ? wFlags : ~0;
+ ITypeInfo *disp_typeinfo;
+ ITypeComp *disp_typecomp;
+ HRESULT hr;
+ UINT i;
- FIXME("(%p)->(%s %08x %d %p %p %p)\n", This, debugstr_w(szName), lHashVal,
+ TRACE("(%p)->(%s %08x %d %p %p %p)\n", This, debugstr_w(szName), lHashVal,
wFlags, ppTInfo, pDescKind, pBindPtr);
- return E_NOTIMPL;
+ if (!szName || !ppTInfo || !pDescKind || !pBindPtr)
+ return E_INVALIDARG;
+
+ for (i = 0; i < This->num_funcs; i++)
+ {
+ if (wcsicmp(szName, This->funcs[i].prop->name)) continue;
+ if (!(flags & INVOKE_FUNC)) return TYPE_E_TYPEMISMATCH;
+
+ hr = ITypeInfo_GetFuncDesc(&This->ITypeInfo_iface, i, &pBindPtr->lpfuncdesc);
+ if (FAILED(hr)) return hr;
+
+ *pDescKind = DESCKIND_FUNCDESC;
+ *ppTInfo = &This->ITypeInfo_iface;
+ ITypeInfo_AddRef(*ppTInfo);
+ return S_OK;
+ }
+
+ for (i = 0; i < This->num_vars; i++)
+ {
+ if (wcsicmp(szName, This->vars[i]->name)) continue;
+ if (!(flags & INVOKE_PROPERTYGET)) return TYPE_E_TYPEMISMATCH;
+
+ hr = ITypeInfo_GetVarDesc(&This->ITypeInfo_iface, i, &pBindPtr->lpvardesc);
+ if (FAILED(hr)) return hr;
+
+ *pDescKind = DESCKIND_VARDESC;
+ *ppTInfo = &This->ITypeInfo_iface;
+ ITypeInfo_AddRef(*ppTInfo);
+ return S_OK;
+ }
+
+ /* Look into the inherited IDispatch */
+ hr = get_dispatch_typeinfo(&disp_typeinfo);
+ if (FAILED(hr)) return hr;
+
+ hr = ITypeInfo_GetTypeComp(disp_typeinfo, &disp_typecomp);
+ if (FAILED(hr)) return hr;
+
+ hr = ITypeComp_Bind(disp_typecomp, szName, lHashVal, wFlags, ppTInfo, pDescKind, pBindPtr);
+ ITypeComp_Release(disp_typecomp);
+ return hr;
}
static HRESULT WINAPI ScriptTypeComp_BindType(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal,
--
2.21.0
Dec. 12, 2019
[PATCH v4 6/9] jscript: Implement ScriptTypeInfo_GetTypeComp.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 64 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 62 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 1ac747b..fb636b4 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -614,6 +614,7 @@ struct typeinfo_func {
typedef struct {
ITypeInfo ITypeInfo_iface;
+ ITypeComp ITypeComp_iface;
LONG ref;
UINT num_funcs;
@@ -629,12 +630,19 @@ static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeInfo(ITypeInfo *iface)
return CONTAINING_RECORD(iface, ScriptTypeInfo, ITypeInfo_iface);
}
+static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeComp(ITypeComp *iface)
+{
+ return CONTAINING_RECORD(iface, ScriptTypeInfo, ITypeComp_iface);
+}
+
static HRESULT WINAPI ScriptTypeInfo_QueryInterface(ITypeInfo *iface, REFIID riid, void **ppv)
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITypeInfo, riid))
*ppv = &This->ITypeInfo_iface;
+ else if (IsEqualGUID(&IID_ITypeComp, riid))
+ *ppv = &This->ITypeComp_iface;
else
{
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
@@ -712,9 +720,13 @@ static HRESULT WINAPI ScriptTypeInfo_GetTypeComp(ITypeInfo *iface, ITypeComp **p
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p)\n", This, ppTComp);
+ TRACE("(%p)->(%p)\n", This, ppTComp);
- return E_NOTIMPL;
+ if (!ppTComp) return E_INVALIDARG;
+
+ *ppTComp = &This->ITypeComp_iface;
+ ITypeInfo_AddRef(iface);
+ return S_OK;
}
static HRESULT WINAPI ScriptTypeInfo_GetFuncDesc(ITypeInfo *iface, UINT index, FUNCDESC **ppFuncDesc)
@@ -979,6 +991,53 @@ static const ITypeInfoVtbl ScriptTypeInfoVtbl = {
ScriptTypeInfo_ReleaseVarDesc
};
+static HRESULT WINAPI ScriptTypeComp_QueryInterface(ITypeComp *iface, REFIID riid, void **ppv)
+{
+ ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface);
+ return ITypeInfo_QueryInterface(&This->ITypeInfo_iface, riid, ppv);
+}
+
+static ULONG WINAPI ScriptTypeComp_AddRef(ITypeComp *iface)
+{
+ ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface);
+ return ITypeInfo_AddRef(&This->ITypeInfo_iface);
+}
+
+static ULONG WINAPI ScriptTypeComp_Release(ITypeComp *iface)
+{
+ ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface);
+ return ITypeInfo_Release(&This->ITypeInfo_iface);
+}
+
+static HRESULT WINAPI ScriptTypeComp_Bind(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal, WORD wFlags,
+ ITypeInfo **ppTInfo, DESCKIND *pDescKind, BINDPTR *pBindPtr)
+{
+ ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface);
+
+ FIXME("(%p)->(%s %08x %d %p %p %p)\n", This, debugstr_w(szName), lHashVal,
+ wFlags, ppTInfo, pDescKind, pBindPtr);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptTypeComp_BindType(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal,
+ ITypeInfo **ppTInfo, ITypeComp **ppTComp)
+{
+ ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface);
+
+ FIXME("(%p)->(%s %08x %p %p)\n", This, debugstr_w(szName), lHashVal, ppTInfo, ppTComp);
+
+ return E_NOTIMPL;
+}
+
+static const ITypeCompVtbl ScriptTypeCompVtbl = {
+ ScriptTypeComp_QueryInterface,
+ ScriptTypeComp_AddRef,
+ ScriptTypeComp_Release,
+ ScriptTypeComp_Bind,
+ ScriptTypeComp_BindType
+};
+
static inline jsdisp_t *impl_from_IDispatchEx(IDispatchEx *iface)
{
return CONTAINING_RECORD(iface, jsdisp_t, IDispatchEx_iface);
@@ -1081,6 +1140,7 @@ static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LC
return E_OUTOFMEMORY;
typeinfo->ITypeInfo_iface.lpVtbl = &ScriptTypeInfoVtbl;
+ typeinfo->ITypeComp_iface.lpVtbl = &ScriptTypeCompVtbl;
typeinfo->ref = 1;
typeinfo->num_vars = num_vars;
typeinfo->num_funcs = num_funcs;
--
2.21.0
Dec. 12, 2019
[PATCH v4 5/9] jscript: Implement ScriptTypeInfo_GetIDsOfNames.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 47 +++++++++++++++++++++++++++++++++++--
dlls/jscript/jscript.h | 1 +
dlls/jscript/jscript_main.c | 25 ++++++++++++++++++++
3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index df87aed..1ac747b 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -802,10 +802,53 @@ static HRESULT WINAPI ScriptTypeInfo_GetIDsOfNames(ITypeInfo *iface, LPOLESTR *r
MEMBERID *pMemId)
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
+ ITypeInfo *disp_typeinfo;
+ const WCHAR *name;
+ HRESULT hr = S_OK;
+ int i, j, arg;
- FIXME("(%p)->(%p %u %p)\n", This, rgszNames, cNames, pMemId);
+ TRACE("(%p)->(%p %u %p)\n", This, rgszNames, cNames, pMemId);
- return E_NOTIMPL;
+ if (!rgszNames || !cNames || !pMemId) return E_INVALIDARG;
+
+ for (i = 0; i < cNames; i++) pMemId[i] = MEMBERID_NIL;
+ name = rgszNames[0];
+
+ for (i = 0; i < This->num_funcs; i++)
+ {
+ struct typeinfo_func *func = &This->funcs[i];
+
+ if (wcsicmp(name, func->prop->name)) continue;
+ pMemId[0] = prop_to_id(This->jsdisp, func->prop);
+
+ for (j = 1; j < cNames; j++)
+ {
+ name = rgszNames[j];
+ for (arg = func->code->param_cnt; --arg >= 0;)
+ if (!wcsicmp(name, func->code->params[arg]))
+ break;
+ if (arg >= 0)
+ pMemId[j] = arg;
+ else
+ hr = DISP_E_UNKNOWNNAME;
+ }
+ return hr;
+ }
+
+ for (i = 0; i < This->num_vars; i++)
+ {
+ dispex_prop_t *var = This->vars[i];
+
+ if (wcsicmp(name, var->name)) continue;
+ pMemId[0] = prop_to_id(This->jsdisp, var);
+ return S_OK;
+ }
+
+ /* Look into the inherited IDispatch */
+ hr = get_dispatch_typeinfo(&disp_typeinfo);
+ if (FAILED(hr)) return hr;
+
+ return ITypeInfo_GetIDsOfNames(disp_typeinfo, rgszNames, cNames, pMemId);
}
static HRESULT WINAPI ScriptTypeInfo_Invoke(ITypeInfo *iface, PVOID pvInstance, MEMBERID memid, WORD wFlags,
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 7174db8..4ec5004 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -87,6 +87,7 @@ static inline LPWSTR heap_strdupW(LPCWSTR str)
typedef struct jsdisp_t jsdisp_t;
extern HINSTANCE jscript_hinstance DECLSPEC_HIDDEN;
+HRESULT get_dispatch_typeinfo(ITypeInfo**) DECLSPEC_HIDDEN;
#define PROPF_ARGMASK 0x00ff
#define PROPF_METHOD 0x0100
diff --git a/dlls/jscript/jscript_main.c b/dlls/jscript/jscript_main.c
index 9f9f412..532cdf9 100644
--- a/dlls/jscript/jscript_main.c
+++ b/dlls/jscript/jscript_main.c
@@ -37,6 +37,30 @@ LONG module_ref = 0;
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
HINSTANCE jscript_hinstance;
+static ITypeInfo *dispatch_typeinfo;
+
+HRESULT get_dispatch_typeinfo(ITypeInfo **out)
+{
+ ITypeInfo *typeinfo;
+ ITypeLib *typelib;
+ HRESULT hr;
+
+ if (!dispatch_typeinfo)
+ {
+ hr = LoadRegTypeLib(&IID_StdOle, STDOLE_MAJORVERNUM, STDOLE_MINORVERNUM, STDOLE_LCID, &typelib);
+ if (FAILED(hr)) return hr;
+
+ hr = ITypeLib_GetTypeInfoOfGuid(typelib, &IID_IDispatch, &typeinfo);
+ ITypeLib_Release(typelib);
+ if (FAILED(hr)) return hr;
+
+ if (InterlockedCompareExchangePointer((void**)&dispatch_typeinfo, typeinfo, NULL))
+ ITypeInfo_Release(typeinfo);
+ }
+
+ *out = dispatch_typeinfo;
+ return S_OK;
+}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
{
@@ -145,6 +169,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
break;
case DLL_PROCESS_DETACH:
if (lpv) break;
+ if (dispatch_typeinfo) ITypeInfo_Release(dispatch_typeinfo);
free_strings();
}
--
2.21.0
Dec. 12, 2019
[PATCH v4 4/9] jscript: Implement ScriptTypeInfo_GetVarDesc.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 1f062fe..df87aed 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -752,10 +752,22 @@ static HRESULT WINAPI ScriptTypeInfo_GetFuncDesc(ITypeInfo *iface, UINT index, F
static HRESULT WINAPI ScriptTypeInfo_GetVarDesc(ITypeInfo *iface, UINT index, VARDESC **ppVarDesc)
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
+ VARDESC *desc;
- FIXME("(%p)->(%u %p)\n", This, index, ppVarDesc);
+ TRACE("(%p)->(%u %p)\n", This, index, ppVarDesc);
- return E_NOTIMPL;
+ if (!ppVarDesc) return E_INVALIDARG;
+ if (index >= This->num_vars) return TYPE_E_ELEMENTNOTFOUND;
+
+ desc = heap_alloc_zero(sizeof(*desc));
+ if (!desc) return E_OUTOFMEMORY;
+
+ desc->memid = prop_to_id(This->jsdisp, This->vars[index]);
+ desc->varkind = VAR_DISPATCH;
+ desc->elemdescVar.tdesc.vt = VT_VARIANT;
+
+ *ppVarDesc = desc;
+ return S_OK;
}
static HRESULT WINAPI ScriptTypeInfo_GetNames(ITypeInfo *iface, MEMBERID memid, BSTR *rgBstrNames,
@@ -894,7 +906,9 @@ static void WINAPI ScriptTypeInfo_ReleaseVarDesc(ITypeInfo *iface, VARDESC *pVar
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p)\n", This, pVarDesc);
+ TRACE("(%p)->(%p)\n", This, pVarDesc);
+
+ heap_free(pVarDesc);
}
static const ITypeInfoVtbl ScriptTypeInfoVtbl = {
--
2.21.0
Dec. 12, 2019
[PATCH v4 3/9] jscript: Implement ScriptTypeInfo_GetFuncDesc.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index ef002e4..1f062fe 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -720,10 +720,33 @@ static HRESULT WINAPI ScriptTypeInfo_GetTypeComp(ITypeInfo *iface, ITypeComp **p
static HRESULT WINAPI ScriptTypeInfo_GetFuncDesc(ITypeInfo *iface, UINT index, FUNCDESC **ppFuncDesc)
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
+ struct typeinfo_func *func;
+ FUNCDESC *desc;
+ unsigned i;
- FIXME("(%p)->(%u %p)\n", This, index, ppFuncDesc);
+ TRACE("(%p)->(%u %p)\n", This, index, ppFuncDesc);
- return E_NOTIMPL;
+ if (!ppFuncDesc) return E_INVALIDARG;
+ if (index >= This->num_funcs) return TYPE_E_ELEMENTNOTFOUND;
+ func = &This->funcs[index];
+
+ /* Store the parameter array after the FUNCDESC structure */
+ desc = heap_alloc_zero(sizeof(*desc) + sizeof(ELEMDESC) * func->code->param_cnt);
+ if (!desc) return E_OUTOFMEMORY;
+
+ desc->memid = prop_to_id(This->jsdisp, func->prop);
+ desc->funckind = FUNC_DISPATCH;
+ desc->invkind = INVOKE_FUNC;
+ desc->callconv = CC_STDCALL;
+ desc->cParams = func->code->param_cnt;
+ desc->elemdescFunc.tdesc.vt = VT_VARIANT;
+
+ if (func->code->param_cnt) desc->lprgelemdescParam = (ELEMDESC*)(desc + 1);
+ for (i = 0; i < func->code->param_cnt; i++)
+ desc->lprgelemdescParam[i].tdesc.vt = VT_VARIANT;
+
+ *ppFuncDesc = desc;
+ return S_OK;
}
static HRESULT WINAPI ScriptTypeInfo_GetVarDesc(ITypeInfo *iface, UINT index, VARDESC **ppVarDesc)
@@ -862,7 +885,9 @@ static void WINAPI ScriptTypeInfo_ReleaseFuncDesc(ITypeInfo *iface, FUNCDESC *pF
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p)\n", This, pFuncDesc);
+ TRACE("(%p)->(%p)\n", This, pFuncDesc);
+
+ heap_free(pFuncDesc);
}
static void WINAPI ScriptTypeInfo_ReleaseVarDesc(ITypeInfo *iface, VARDESC *pVarDesc)
--
2.21.0
Dec. 12, 2019
[PATCH v4 2/9] jscript: Implement ScriptTypeInfo_GetTypeAttr.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 36 +++++++++++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 6c6d25a..ef002e4 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -25,6 +25,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+static const GUID GUID_JScriptTypeInfo = {0xc59c6b12,0xf6c1,0x11cf,{0x88,0x35,0x00,0xa0,0xc9,0x11,0xe8,0xb2}};
+
#define FDEX_VERSION_MASK 0xf0000000
#define GOLDEN_RATIO 0x9E3779B9U
@@ -678,10 +680,32 @@ static ULONG WINAPI ScriptTypeInfo_Release(ITypeInfo *iface)
static HRESULT WINAPI ScriptTypeInfo_GetTypeAttr(ITypeInfo *iface, TYPEATTR **ppTypeAttr)
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
-
- FIXME("(%p)->(%p)\n", This, ppTypeAttr);
-
- return E_NOTIMPL;
+ TYPEATTR *attr;
+
+ TRACE("(%p)->(%p)\n", This, ppTypeAttr);
+
+ if (!ppTypeAttr) return E_INVALIDARG;
+
+ attr = heap_alloc_zero(sizeof(*attr));
+ if (!attr) return E_OUTOFMEMORY;
+
+ attr->guid = GUID_JScriptTypeInfo;
+ attr->lcid = LOCALE_USER_DEFAULT;
+ attr->memidConstructor = MEMBERID_NIL;
+ attr->memidDestructor = MEMBERID_NIL;
+ attr->cbSizeInstance = 4;
+ attr->typekind = TKIND_DISPATCH;
+ attr->cFuncs = This->num_funcs;
+ attr->cVars = This->num_vars;
+ attr->cImplTypes = 1;
+ attr->cbSizeVft = sizeof(IDispatchVtbl);
+ attr->cbAlignment = 4;
+ attr->wTypeFlags = TYPEFLAG_FDISPATCHABLE;
+ attr->wMajorVerNum = JSCRIPT_MAJOR_VERSION;
+ attr->wMinorVerNum = JSCRIPT_MINOR_VERSION;
+
+ *ppTypeAttr = attr;
+ return S_OK;
}
static HRESULT WINAPI ScriptTypeInfo_GetTypeComp(ITypeInfo *iface, ITypeComp **ppTComp)
@@ -829,7 +853,9 @@ static void WINAPI ScriptTypeInfo_ReleaseTypeAttr(ITypeInfo *iface, TYPEATTR *pT
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p)\n", This, pTypeAttr);
+ TRACE("(%p)->(%p)\n", This, pTypeAttr);
+
+ heap_free(pTypeAttr);
}
static void WINAPI ScriptTypeInfo_ReleaseFuncDesc(ITypeInfo *iface, FUNCDESC *pFuncDesc)
--
2.21.0
Dec. 12, 2019
[PATCH v4 1/9] jscript: Store the necessary function and variable info in the TypeInfo.
by Gabriel Ivăncescu
The TypeInfo is built when it is retrieved and frozen at that moment, even
if the script changes after that and more identifiers are added to it,
or existing ones deleted.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 110 ++++++++++++++++++++++++++++++++++++++++
dlls/jscript/function.c | 31 +++++++++++
dlls/jscript/jscript.h | 1 +
3 files changed, 142 insertions(+)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 92e9b96..6c6d25a 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include "jscript.h"
+#include "engine.h"
#include "wine/debug.h"
@@ -70,6 +71,20 @@ static inline dispex_prop_t *get_prop(jsdisp_t *This, DISPID id)
return This->props+id;
}
+static inline BOOL is_function_prop(dispex_prop_t *prop)
+{
+ BOOL ret = FALSE;
+
+ if (is_object_instance(prop->u.val))
+ {
+ jsdisp_t *jsdisp = iface_to_jsdisp(get_object(prop->u.val));
+
+ if (jsdisp) ret = is_class(jsdisp, JSCLASS_FUNCTION);
+ jsdisp_release(jsdisp);
+ }
+ return ret;
+}
+
static DWORD get_flags(jsdisp_t *This, dispex_prop_t *prop)
{
if(prop->type == PROP_PROTREF) {
@@ -590,9 +605,21 @@ static HRESULT fill_protrefs(jsdisp_t *This)
return S_OK;
}
+struct typeinfo_func {
+ dispex_prop_t *prop;
+ function_code_t *code;
+};
+
typedef struct {
ITypeInfo ITypeInfo_iface;
LONG ref;
+
+ UINT num_funcs;
+ UINT num_vars;
+ struct typeinfo_func *funcs;
+ dispex_prop_t **vars;
+
+ jsdisp_t *jsdisp;
} ScriptTypeInfo;
static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeInfo(ITypeInfo *iface)
@@ -632,11 +659,17 @@ static ULONG WINAPI ScriptTypeInfo_Release(ITypeInfo *iface)
{
ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
LONG ref = InterlockedDecrement(&This->ref);
+ UINT i;
TRACE("(%p) ref=%d\n", This, ref);
if (!ref)
{
+ for (i = This->num_funcs; i--;)
+ release_bytecode(This->funcs[i].code->bytecode);
+ IDispatchEx_Release(&This->jsdisp->IDispatchEx_iface);
+ heap_free(This->funcs);
+ heap_free(This->vars);
heap_free(This);
}
return ref;
@@ -897,17 +930,94 @@ static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LC
ITypeInfo **ppTInfo)
{
jsdisp_t *This = impl_from_IDispatchEx(iface);
+ dispex_prop_t *prop, *cur, *end, **typevar;
+ UINT num_funcs = 0, num_vars = 0;
+ struct typeinfo_func *typefunc;
+ function_code_t *func_code;
ScriptTypeInfo *typeinfo;
+ unsigned pos;
TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
if (iTInfo != 0) return DISP_E_BADINDEX;
+ for (prop = This->props, end = prop + This->prop_cnt; prop != end; prop++)
+ {
+ if (!prop->name || prop->type != PROP_JSVAL || !(prop->flags & PROPF_ENUMERABLE))
+ continue;
+
+ /* If two identifiers differ only by case, the TypeInfo fails */
+ pos = This->props[get_props_idx(This, prop->hash)].bucket_head;
+ while (pos)
+ {
+ cur = This->props + pos;
+
+ if (prop->hash == cur->hash && prop != cur &&
+ cur->type == PROP_JSVAL && (cur->flags & PROPF_ENUMERABLE) &&
+ !wcsicmp(prop->name, cur->name))
+ {
+ return TYPE_E_AMBIGUOUSNAME;
+ }
+ pos = cur->bucket_next;
+ }
+
+ if (is_function_prop(prop))
+ {
+ if (Function_get_code(as_jsdisp(get_object(prop->u.val))))
+ num_funcs++;
+ }
+ else num_vars++;
+ }
+
if (!(typeinfo = heap_alloc(sizeof(*typeinfo))))
return E_OUTOFMEMORY;
typeinfo->ITypeInfo_iface.lpVtbl = &ScriptTypeInfoVtbl;
typeinfo->ref = 1;
+ typeinfo->num_vars = num_vars;
+ typeinfo->num_funcs = num_funcs;
+ typeinfo->jsdisp = This;
+
+ typeinfo->funcs = heap_alloc(sizeof(*typeinfo->funcs) * num_funcs);
+ if (!typeinfo->funcs)
+ {
+ heap_free(typeinfo);
+ return E_OUTOFMEMORY;
+ }
+
+ typeinfo->vars = heap_alloc(sizeof(*typeinfo->vars) * num_vars);
+ if (!typeinfo->vars)
+ {
+ heap_free(typeinfo->funcs);
+ heap_free(typeinfo);
+ return E_OUTOFMEMORY;
+ }
+
+ typefunc = typeinfo->funcs;
+ typevar = typeinfo->vars;
+ for (prop = This->props; prop != end; prop++)
+ {
+ if (!prop->name || prop->type != PROP_JSVAL || !(prop->flags & PROPF_ENUMERABLE))
+ continue;
+
+ if (is_function_prop(prop))
+ {
+ func_code = Function_get_code(as_jsdisp(get_object(prop->u.val)));
+ if (!func_code) continue;
+
+ typefunc->prop = prop;
+ typefunc->code = func_code;
+ typefunc++;
+
+ /* The function may be deleted, so keep a ref */
+ bytecode_addref(func_code->bytecode);
+ }
+ else
+ *typevar++ = prop;
+ }
+
+ /* Keep a ref to the props and their names */
+ IDispatchEx_AddRef(&This->IDispatchEx_iface);
*ppTInfo = &typeinfo->ITypeInfo_iface;
return S_OK;
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index 7a44f50..52c1267 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -37,6 +37,7 @@ typedef struct {
struct _function_vtbl_t {
HRESULT (*call)(script_ctx_t*,FunctionInstance*,IDispatch*,unsigned,unsigned,jsval_t*,jsval_t*);
HRESULT (*toString)(FunctionInstance*,jsstr_t**);
+ function_code_t* (*get_code)(FunctionInstance*);
void (*destructor)(FunctionInstance*);
};
@@ -524,6 +525,16 @@ static HRESULT Function_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval
return S_OK;
}
+function_code_t *Function_get_code(jsdisp_t *jsthis)
+{
+ FunctionInstance *function;
+
+ assert(is_class(jsthis, JSCLASS_FUNCTION));
+ function = function_from_jsdisp(jsthis);
+
+ return function->vtbl->get_code(function);
+}
+
static void Function_destructor(jsdisp_t *dispex)
{
FunctionInstance *function = function_from_jsdisp(dispex);
@@ -638,6 +649,11 @@ static HRESULT NativeFunction_toString(FunctionInstance *func, jsstr_t **ret)
return S_OK;
}
+static function_code_t *NativeFunction_get_code(FunctionInstance *function)
+{
+ return NULL;
+}
+
static void NativeFunction_destructor(FunctionInstance *function)
{
}
@@ -645,6 +661,7 @@ static void NativeFunction_destructor(FunctionInstance *function)
static const function_vtbl_t NativeFunctionVtbl = {
NativeFunction_call,
NativeFunction_toString,
+ NativeFunction_get_code,
NativeFunction_destructor
};
@@ -749,6 +766,13 @@ static HRESULT InterpretedFunction_toString(FunctionInstance *func, jsstr_t **re
return *ret ? S_OK : E_OUTOFMEMORY;
}
+static function_code_t *InterpretedFunction_get_code(FunctionInstance *func)
+{
+ InterpretedFunction *function = (InterpretedFunction*)func;
+
+ return function->func_code;
+}
+
static void InterpretedFunction_destructor(FunctionInstance *func)
{
InterpretedFunction *function = (InterpretedFunction*)func;
@@ -761,6 +785,7 @@ static void InterpretedFunction_destructor(FunctionInstance *func)
static const function_vtbl_t InterpretedFunctionVtbl = {
InterpretedFunction_call,
InterpretedFunction_toString,
+ InterpretedFunction_get_code,
InterpretedFunction_destructor
};
@@ -842,6 +867,11 @@ static HRESULT BindFunction_toString(FunctionInstance *function, jsstr_t **ret)
return *ret ? S_OK : E_OUTOFMEMORY;
}
+static function_code_t *BindFunction_get_code(FunctionInstance *function)
+{
+ return NULL;
+}
+
static void BindFunction_destructor(FunctionInstance *func)
{
BindFunction *function = (BindFunction*)func;
@@ -858,6 +888,7 @@ static void BindFunction_destructor(FunctionInstance *func)
static const function_vtbl_t BindFunctionVtbl = {
BindFunction_call,
BindFunction_toString,
+ BindFunction_get_code,
BindFunction_destructor
};
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 5d635b7..7174db8 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -307,6 +307,7 @@ HRESULT Function_invoke(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DE
HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT Function_get_value(script_ctx_t*,jsdisp_t*,jsval_t*) DECLSPEC_HIDDEN;
+struct _function_code_t *Function_get_code(jsdisp_t*) DECLSPEC_HIDDEN;
#define DEFAULT_FUNCTION_VALUE {NULL, Function_value,0, Function_get_value}
HRESULT throw_eval_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
--
2.21.0
Dec. 12, 2019
[PATCH] testbot/Build: Update the Gecko download URL.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/Build/Utils.pm | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/testbot/lib/Build/Utils.pm b/testbot/lib/Build/Utils.pm
index 15acf6783..a8e5a0e0e 100644
--- a/testbot/lib/Build/Utils.pm
+++ b/testbot/lib/Build/Utils.pm
@@ -314,8 +314,7 @@ sub _UpdateAddOn($$$)
return 0;
}
- $AddOn->{filename} = "wine". ($Name eq "gecko" ? "_" : "-") .
- "$Name-$AddOn->{version}".
+ $AddOn->{filename} = "wine-$Name-$AddOn->{version}".
($Arch eq "" ? "" : "-$Arch") .".msi";
return 1 if (!_VerifyAddOn($AddOn, $Arch));
--
2.20.1
Dec. 12, 2019
[PATCH vkd3d 2/2] vkd3d: Use multiple command queues if available.
by Conor McCarthy
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
libs/vkd3d/command.c | 24 +++++++----
libs/vkd3d/device.c | 84 ++++++++++++++++++++++++--------------
libs/vkd3d/vkd3d_private.h | 16 ++++++--
3 files changed, 83 insertions(+), 41 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 8a7ff66..6b0d9e0 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -22,7 +22,8 @@
static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkFence vk_fence);
HRESULT vkd3d_queue_create(struct d3d12_device *device,
- uint32_t family_index, const VkQueueFamilyProperties *properties, struct vkd3d_queue **queue)
+ uint32_t family_index, const VkQueueFamilyProperties *properties,
+ struct vkd3d_queue_array *queue_array, uint32_t queue_index)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct vkd3d_queue *object;
@@ -51,11 +52,11 @@ HRESULT vkd3d_queue_create(struct d3d12_device *device,
memset(object->old_vk_semaphores, 0, sizeof(object->old_vk_semaphores));
- VK_CALL(vkGetDeviceQueue(device->vk_device, family_index, 0, &object->vk_queue));
+ VK_CALL(vkGetDeviceQueue(device->vk_device, family_index, queue_index, &object->vk_queue));
TRACE("Created queue %p for queue family index %u.\n", object, family_index);
- *queue = object;
+ queue_array->queues[queue_index] = object;
return S_OK;
}
@@ -1683,17 +1684,26 @@ static struct d3d12_command_allocator *unsafe_impl_from_ID3D12CommandAllocator(I
return impl_from_ID3D12CommandAllocator(iface);
}
+static struct vkd3d_queue *d3d12_device_get_next_vkd3d_queue(struct vkd3d_queue_array *queue_array)
+{
+ LONG i = (InterlockedIncrement(queue_array->index_ptr) - 1) % VKD3D_MAX_QUEUE_CREATE_COUNT;
+ struct vkd3d_queue *queue = queue_array->queues[i];
+ if (queue)
+ return queue;
+ return queue_array->queues[0];
+}
+
struct vkd3d_queue *d3d12_device_get_vkd3d_queue(struct d3d12_device *device,
D3D12_COMMAND_LIST_TYPE type)
{
switch (type)
{
case D3D12_COMMAND_LIST_TYPE_DIRECT:
- return device->direct_queue;
+ return d3d12_device_get_next_vkd3d_queue(&device->direct_queues);
case D3D12_COMMAND_LIST_TYPE_COMPUTE:
- return device->compute_queue;
+ return d3d12_device_get_next_vkd3d_queue(&device->compute_queues);
case D3D12_COMMAND_LIST_TYPE_COPY:
- return device->copy_queue;
+ return d3d12_device_get_next_vkd3d_queue(&device->copy_queues);
default:
FIXME("Unhandled command list type %#x.\n", type);
return NULL;
@@ -1713,7 +1723,7 @@ static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allo
return hr;
if (!(queue = d3d12_device_get_vkd3d_queue(device, type)))
- queue = device->direct_queue;
+ queue = device->direct_queues.queues[0];
allocator->ID3D12CommandAllocator_iface.lpVtbl = &d3d12_command_allocator_vtbl;
allocator->refcount = 1;
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index ad32ff2..ff5dad1 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1538,17 +1538,48 @@ struct vkd3d_device_queue_info
static void d3d12_device_destroy_vkd3d_queues(struct d3d12_device *device)
{
- if (device->direct_queue)
- vkd3d_queue_destroy(device->direct_queue, device);
- if (device->compute_queue && device->compute_queue != device->direct_queue)
- vkd3d_queue_destroy(device->compute_queue, device);
- if (device->copy_queue && device->copy_queue != device->direct_queue
- && device->copy_queue != device->compute_queue)
- vkd3d_queue_destroy(device->copy_queue, device);
+ struct vkd3d_queue_array *direct_queues = &device->direct_queues;
+ struct vkd3d_queue_array *compute_queues = &device->compute_queues;
+ struct vkd3d_queue_array *copy_queues = &device->copy_queues;
+ size_t i;
- device->direct_queue = NULL;
- device->compute_queue = NULL;
- device->copy_queue = NULL;
+ for (i = 0; i < ARRAY_SIZE(direct_queues->queues); ++i)
+ {
+ if (direct_queues->queues[i])
+ vkd3d_queue_destroy(direct_queues->queues[i], device);
+ if (compute_queues->queues[i] && compute_queues->queues[i] != direct_queues->queues[i])
+ vkd3d_queue_destroy(compute_queues->queues[i], device);
+ if (copy_queues->queues[i] && copy_queues->queues[i] != direct_queues->queues[i]
+ && copy_queues->queues[i] != compute_queues->queues[i])
+ vkd3d_queue_destroy(copy_queues->queues[i], device);
+ direct_queues->queues[i] = NULL;
+ compute_queues->queues[i] = NULL;
+ copy_queues->queues[i] = NULL;
+ }
+}
+
+static HRESULT d3d12_device_create_family_queues(struct d3d12_device *device,
+ const struct vkd3d_device_queue_info *queue_info, enum vkd3d_queue_family family,
+ struct vkd3d_queue_array *queue_array)
+{
+ uint32_t family_index = queue_info->family_index[family];
+ uint32_t i, count;
+ HRESULT hr;
+
+ queue_array->index_ptr = &queue_array->index;
+
+ count = min(queue_info->vk_properties[family].queueCount, VKD3D_MAX_QUEUE_CREATE_COUNT);
+
+ for (i = 0; i < count; ++i)
+ {
+ if (FAILED(hr = vkd3d_queue_create(device, family_index,
+ &queue_info->vk_properties[family], queue_array, i)))
+ return hr;
+ }
+
+ device->queue_family_indices[device->queue_family_count++] = family_index;
+
+ return S_OK;
}
static HRESULT d3d12_device_create_vkd3d_queues(struct d3d12_device *device,
@@ -1559,35 +1590,27 @@ static HRESULT d3d12_device_create_vkd3d_queues(struct d3d12_device *device,
uint32_t direct_family_index = queue_info->family_index[VKD3D_QUEUE_FAMILY_DIRECT];
HRESULT hr;
- device->direct_queue = NULL;
- device->compute_queue = NULL;
- device->copy_queue = NULL;
+ memset(&device->direct_queues, 0, sizeof(device->direct_queues));
+ memset(&device->compute_queues, 0, sizeof(device->compute_queues));
+ memset(&device->copy_queues, 0, sizeof(device->copy_queues));
device->queue_family_count = 0;
memset(device->queue_family_indices, 0, sizeof(device->queue_family_indices));
- if (SUCCEEDED((hr = vkd3d_queue_create(device, direct_family_index,
- &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_DIRECT], &device->direct_queue))))
- device->queue_family_indices[device->queue_family_count++] = direct_family_index;
- else
+ if (FAILED(hr = d3d12_device_create_family_queues(device, queue_info, VKD3D_QUEUE_FAMILY_DIRECT, &device->direct_queues)))
goto out_destroy_queues;
+ /* A binary copy points index_ptr to the index in the source object, which is the desired behaviour. */
if (compute_family_index == direct_family_index)
- device->compute_queue = device->direct_queue;
- else if (SUCCEEDED(hr = vkd3d_queue_create(device, compute_family_index,
- &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_COMPUTE], &device->compute_queue)))
- device->queue_family_indices[device->queue_family_count++] = compute_family_index;
- else
+ memcpy(&device->compute_queues, &device->direct_queues, sizeof(device->compute_queues));
+ else if (FAILED(hr = d3d12_device_create_family_queues(device, queue_info, VKD3D_QUEUE_FAMILY_COMPUTE, &device->compute_queues)))
goto out_destroy_queues;
if (transfer_family_index == direct_family_index)
- device->copy_queue = device->direct_queue;
+ memcpy(&device->copy_queues, &device->direct_queues, sizeof(device->copy_queues));
else if (transfer_family_index == compute_family_index)
- device->copy_queue = device->compute_queue;
- else if (SUCCEEDED(hr = vkd3d_queue_create(device, transfer_family_index,
- &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_TRANSFER], &device->copy_queue)))
- device->queue_family_indices[device->queue_family_count++] = transfer_family_index;
- else
+ memcpy(&device->copy_queues, &device->compute_queues, sizeof(device->copy_queues));
+ else if (FAILED(hr = d3d12_device_create_family_queues(device, queue_info, VKD3D_QUEUE_FAMILY_TRANSFER, &device->copy_queues)))
goto out_destroy_queues;
return S_OK;
@@ -1597,7 +1620,8 @@ out_destroy_queues:
return hr;
}
-static float queue_priorities[] = {1.0f};
+static float queue_priorities[] = {1.0f, 1.0f, 1.0f, 1.0f};
+STATIC_ASSERT(ARRAY_SIZE(queue_priorities) == VKD3D_MAX_QUEUE_CREATE_COUNT);
static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance,
VkPhysicalDevice physical_device, struct vkd3d_device_queue_info *info)
@@ -1647,7 +1671,7 @@ static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance,
queue_info->pNext = NULL;
queue_info->flags = 0;
queue_info->queueFamilyIndex = i;
- queue_info->queueCount = 1; /* FIXME: Use multiple queues. */
+ queue_info->queueCount = min(queue_properties[i].queueCount, VKD3D_MAX_QUEUE_CREATE_COUNT);
queue_info->pQueuePriorities = queue_priorities;
}
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 0c031d2..382b5ca 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -50,6 +50,7 @@
#define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u
#define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u
+#define VKD3D_MAX_QUEUE_CREATE_COUNT 4u
#define VKD3D_MAX_SHADER_EXTENSIONS 1u
#define VKD3D_MAX_SHADER_STAGES 5u
#define VKD3D_MAX_VK_SYNC_OBJECTS 4u
@@ -1003,10 +1004,17 @@ struct vkd3d_queue
VkSemaphore old_vk_semaphores[VKD3D_MAX_VK_SYNC_OBJECTS];
};
+struct vkd3d_queue_array
+{
+ struct vkd3d_queue *queues[VKD3D_MAX_QUEUE_CREATE_COUNT];
+ LONG *index_ptr;
+ LONG index;
+};
+
VkQueue vkd3d_queue_acquire(struct vkd3d_queue *queue) DECLSPEC_HIDDEN;
HRESULT vkd3d_queue_create(struct d3d12_device *device,
uint32_t family_index, const VkQueueFamilyProperties *properties,
- struct vkd3d_queue **queue) DECLSPEC_HIDDEN;
+ struct vkd3d_queue_array *queue_array, uint32_t queue_index) DECLSPEC_HIDDEN;
void vkd3d_queue_destroy(struct vkd3d_queue *queue, struct d3d12_device *device) DECLSPEC_HIDDEN;
void vkd3d_queue_release(struct vkd3d_queue *queue) DECLSPEC_HIDDEN;
@@ -1134,9 +1142,9 @@ struct d3d12_device
struct vkd3d_vulkan_info vk_info;
- struct vkd3d_queue *direct_queue;
- struct vkd3d_queue *compute_queue;
- struct vkd3d_queue *copy_queue;
+ struct vkd3d_queue_array direct_queues;
+ struct vkd3d_queue_array compute_queues;
+ struct vkd3d_queue_array copy_queues;
uint32_t queue_family_indices[VKD3D_MAX_QUEUE_FAMILY_COUNT];
unsigned int queue_family_count;
--
2.24.0
Dec. 12, 2019
[PATCH vkd3d 1/2] vkd3d: Map the copy queue to the compute queue if necessary and possible.
by Conor McCarthy
The current implementation maps copy to direct unless a dedicated copy
queue is present. Compute queues are often more lightly loaded and there
is usually more than one available.
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
libs/vkd3d/device.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 757d4ac..ad32ff2 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1667,8 +1667,16 @@ static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance,
}
if (info->family_index[VKD3D_QUEUE_FAMILY_TRANSFER] == ~0u)
{
- info->family_index[VKD3D_QUEUE_FAMILY_TRANSFER] = info->family_index[VKD3D_QUEUE_FAMILY_DIRECT];
- info->vk_properties[VKD3D_QUEUE_FAMILY_TRANSFER] = info->vk_properties[VKD3D_QUEUE_FAMILY_DIRECT];
+ if (info->vk_properties[VKD3D_QUEUE_FAMILY_COMPUTE].queueFlags & VK_QUEUE_TRANSFER_BIT)
+ {
+ info->family_index[VKD3D_QUEUE_FAMILY_TRANSFER] = info->family_index[VKD3D_QUEUE_FAMILY_COMPUTE];
+ info->vk_properties[VKD3D_QUEUE_FAMILY_TRANSFER] = info->vk_properties[VKD3D_QUEUE_FAMILY_COMPUTE];
+ }
+ else
+ {
+ info->family_index[VKD3D_QUEUE_FAMILY_TRANSFER] = info->family_index[VKD3D_QUEUE_FAMILY_DIRECT];
+ info->vk_properties[VKD3D_QUEUE_FAMILY_TRANSFER] = info->vk_properties[VKD3D_QUEUE_FAMILY_DIRECT];
+ }
}
/* Compact the array. */
--
2.24.0
Dec. 12, 2019
Re: [PATCH v3 4/4] kernel32/tests: Test std handle inheritance in test_parent_process_attribute().
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=62020
Your paranoid android.
=== w1064v1507 (32 bit report) ===
kernel32:
0e38:process:proce 1 sts.c:2925: Test failed: WaitFoerSinglesObject returnted 258
Report errors:
kernel32:process is missing some failure messages
=== wvistau64 (64 bit report) ===
kernel32:
process.c:1228: Test failed: expected 1, got 0
process.c:1231: Test failed: Child process termination
process.c:1235: Test failed: Toolhelp:cntUsage expected 0, but got 1
process.c:1236: Test failed: Toolhelp:th32DefaultHeapID expected 0, but got 1
process.c:1237: Test failed: Toolhelp:th32ModuleID expected 0, but got 1
process.c:1238: Test failed: Toolhelp:th32ParentProcessID expected 1428, but got 0
process.c:1240: Test failed: Toolhelp:dwFlags expected 0, but got 1
Dec. 12, 2019
Re: [PATCH v3 3/4] kernel32/tests: Test invalid parent handle in test_parent_process_attribute().
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=62019
Your paranoid android.
=== wvistau64 (64 bit report) ===
kernel32:
process.c:1226: Test failed: expected 1, got 0
process.c:1229: Test failed: Child process termination
process.c:1233: Test failed: Toolhelp:cntUsage expected 0, but got 1
process.c:1234: Test failed: Toolhelp:th32DefaultHeapID expected 0, but got 1
process.c:1235: Test failed: Toolhelp:th32ModuleID expected 0, but got 1
process.c:1236: Test failed: Toolhelp:th32ParentProcessID expected 1428, but got 0
process.c:1238: Test failed: Toolhelp:dwFlags expected 0, but got 1
Dec. 12, 2019
[PATCH] include: Add missing defines for tokens in winnt.h
by Vijay Kiran Kamuju
Signed-off-by: Vijay Kiran Kamuju <infyquest(a)gmail.com>
---
include/winnt.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/winnt.h b/include/winnt.h
index 1db7fdd28e..56734f178d 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -4177,6 +4177,11 @@ typedef enum _TOKEN_INFORMATION_CLASS {
MaxTokenInfoClass
} TOKEN_INFORMATION_CLASS;
+#define DISABLE_MAX_PRIVILEGE 0x1
+#define SANDBOX_INERT 0x2
+#define LUA_TOKEN 0x4
+#define WRITE_RESTRICTED 0x8
+
#define TOKEN_TOKEN_ADJUST_DEFAULT 0x0080
#define TOKEN_ADJUST_GROUPS 0x0040
#define TOKEN_ADJUST_PRIVILEGES 0x0020
--
2.21.0
Dec. 12, 2019
[PATCH] ole32/tests: Fix return value trace.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/ole32/tests/clipboard.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c
index 8901758034..b97c2646bf 100644
--- a/dlls/ole32/tests/clipboard.c
+++ b/dlls/ole32/tests/clipboard.c
@@ -1014,7 +1014,8 @@ static void test_set_clipboard(void)
test_cf_dataobject(data_cmpl);
test_enum_fmtetc(data_cmpl);
- ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard, hr = 0x%08x\n", hr);
+ hr = OleSetClipboard(NULL);
+ ok(hr == S_OK, "failed to clear clipboard, hr = 0x%08x.\n", hr);
test_no_cf_dataobject();
test_enum_fmtetc(NULL);
--
2.24.0
Dec. 12, 2019
Re: [PATCH 4/5] ole32: Get rid of casts in GUID serialization helper.
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=62013
Your paranoid android.
=== debian10 (32 bit Chinese:China report) ===
ole32:
clipboard.c:1484: Test failed: got 800401d0
clipboard.c:1485: Test failed: got 0
Dec. 12, 2019
[PATCH v3 4/4] kernel32/tests: Test std handle inheritance in test_parent_process_attribute().
by Paul Gofman
Signed-off-by: Paul Gofman <gofmanp(a)gmail.com>
---
v2:
- added test;
v3:
- no changes.
dlls/kernel32/tests/process.c | 55 ++++++++++++++++++++++++++++-------
1 file changed, 45 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 1194c54202..92838c09ff 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -92,6 +92,7 @@ static SIZE_T (WINAPI *pGetLargePageMinimum)(void);
static BOOL (WINAPI *pInitializeProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD, SIZE_T*);
static BOOL (WINAPI *pUpdateProcThreadAttribute)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD_PTR, void *,SIZE_T,void*,SIZE_T*);
static void (WINAPI *pDeleteProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*);
+static DWORD (WINAPI *pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD);
/* ############################### */
static char base[MAX_PATH];
@@ -259,6 +260,7 @@ static BOOL init(void)
pInitializeProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "InitializeProcThreadAttributeList");
pUpdateProcThreadAttribute = (void *)GetProcAddress(hkernel32, "UpdateProcThreadAttribute");
pDeleteProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "DeleteProcThreadAttributeList");
+ pGetFinalPathNameByHandleA = (void *)GetProcAddress(hkernel32, "GetFinalPathNameByHandleA");
return TRUE;
}
@@ -3827,7 +3829,7 @@ static void test_ProcThreadAttributeList(void)
* level 2: Process created by level 1 process with handle inheritance and level 0
* process parent substitute.
* level 255: Process created by level 1 process during invalid parent handles testing. */
-void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
+void test_parent_process_attribute(unsigned int level, HANDLE read_pipe, HANDLE creator_stdhandle)
{
PROCESS_BASIC_INFORMATION pbi;
char buffer[MAX_PATH + 64];
@@ -3837,7 +3839,9 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
STARTUPINFOEXA si;
DWORD parent_id;
NTSTATUS status;
+ DWORD exit_code;
ULONG pbi_size;
+ HANDLE hstderr;
HANDLE parent;
DWORD size;
BOOL ret;
@@ -3885,8 +3889,24 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
if (level == 2)
{
+ char file_path[MAX_PATH];
+
ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n",
parent_id, parent_data.parent_id);
+
+ GetStartupInfoA(&si.StartupInfo);
+ hstderr = si.StartupInfo.hStdError;
+
+ /* On Windows, std handle values are copied from creator process but seems not to be inherited from it.
+ * Some operation on such handle may sometimes succeed, but various way of quering information
+ * from such handle suggest that the handle refers to some other object.
+ * Windows seem to just keep the handle value, even for invalid handle. It does not always work exacly
+ * like that in Wine now due to special handling of console handles in kernelbase/process.c:create_process_params()
+ * and initialization in dlls/msvcrt: msvcrt_init_io(). */
+ ok(hstderr == creator_stdhandle, "Unexpected hstderr %p, creator_hstdhandle %p.\n",
+ hstderr, creator_stdhandle);
+ size = pGetFinalPathNameByHandleA(hstderr, file_path, sizeof(file_path), FILE_NAME_NORMALIZED);
+ ok(!size, "Got unexpected size %u.\n", size);
return;
}
@@ -3902,7 +3922,7 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
- sprintf(buffer, "\"%s\" tests/process.c parent %u %p", selfname, 255, read_pipe);
+ sprintf(buffer, "\"%s\" tests/process.c parent %u %p %p", selfname, 255, read_pipe, NULL);
#if 0
/* Crashes on some Windows installations, otherwise successfully creates process. */
@@ -3988,9 +4008,17 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
&parent, sizeof(parent), NULL, NULL);
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+
+ hstderr = CreateFileA("stderr_1.tmp", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ ok(hstderr != INVALID_HANDLE_VALUE, "Could not create file, GetLastError() %u.\n", GetLastError());
+ si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+ si.StartupInfo.hStdError = hstderr;
+ si.StartupInfo.hStdOutput = creator_stdhandle;
}
- sprintf(buffer, "\"%s\" tests/process.c parent %u %p", selfname, level + 1, read_pipe);
+ sprintf(buffer, "\"%s\" tests/process.c parent %u %p %p", selfname, level + 1, read_pipe,
+ level ? hstderr : GetStdHandle(STD_OUTPUT_HANDLE));
ret = CreateProcessA(NULL, buffer, NULL, NULL, level == 1, level == 1 ? EXTENDED_STARTUPINFO_PRESENT : 0,
NULL, NULL, (STARTUPINFOA *)&si, &info);
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
@@ -4008,10 +4036,16 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ GetExitCodeProcess(info.hProcess, &exit_code);
+ ok(!exit_code, "Child test failed, exit_code %#x.\n", exit_code);
+
CloseHandle(info.hThread);
CloseHandle(info.hProcess);
-
- if (!level)
+ if (level)
+ {
+ CloseHandle(hstderr);
+ }
+ else
{
CloseHandle(read_pipe);
CloseHandle(write_pipe);
@@ -4062,12 +4096,13 @@ START_TEST(process)
CloseHandle(info.hThread);
return;
}
- else if (!strcmp(myARGV[2], "parent") && myARGC >= 5)
+ else if (!strcmp(myARGV[2], "parent") && myARGC >= 6)
{
- HANDLE h;
+ HANDLE h1, h2;
- sscanf(myARGV[4], "%p", &h);
- test_parent_process_attribute(atoi(myARGV[3]), h);
+ sscanf(myARGV[4], "%p", &h1);
+ sscanf(myARGV[5], "%p", &h2);
+ test_parent_process_attribute(atoi(myARGV[3]), h1, h2);
return;
}
@@ -4136,5 +4171,5 @@ START_TEST(process)
test_jobInheritance(job);
test_BreakawayOk(job);
CloseHandle(job);
- test_parent_process_attribute(0, NULL);
+ test_parent_process_attribute(0, NULL, NULL);
}
--
2.23.0
Dec. 12, 2019
[PATCH v3 3/4] kernel32/tests: Test invalid parent handle in test_parent_process_attribute().
by Paul Gofman
Signed-off-by: Paul Gofman <gofmanp(a)gmail.com>
---
v2:
- no changes;
v3:
- mark failed child process creation for GetCurrentProcess() parent handle
as broken instead of successful creation;
- replace test with INVALID_HANDLE_VALUE parent (which is the same as GetCurrentProcess())
with OpenProcess(..., GetCurrentProcessId()) handle.
dlls/kernel32/tests/process.c | 85 ++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 6d7a9a74c3..1194c54202 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -3825,7 +3825,8 @@ static void test_ProcThreadAttributeList(void)
/* level 0: Main test process
* level 1: Process created by level 0 process without handle inheritance
* level 2: Process created by level 1 process with handle inheritance and level 0
- * process parent substitute. */
+ * process parent substitute.
+ * level 255: Process created by level 1 process during invalid parent handles testing. */
void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
{
PROCESS_BASIC_INFORMATION pbi;
@@ -3848,6 +3849,9 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
}
parent_data;
+ if (level == 255)
+ return;
+
if (!pInitializeProcThreadAttributeList)
{
win_skip("No support for ProcThreadAttributeList.\n");
@@ -3891,11 +3895,90 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
if (level)
{
+ HANDLE handle;
SIZE_T size;
ret = pInitializeProcThreadAttributeList(NULL, 1, 0, &size);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+
+ sprintf(buffer, "\"%s\" tests/process.c parent %u %p", selfname, 255, read_pipe);
+
+#if 0
+ /* Crashes on some Windows installations, otherwise successfully creates process. */
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT,
+ NULL, NULL, (STARTUPINFOA *)&si, &info);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ CloseHandle(info.hThread);
+ CloseHandle(info.hProcess);
+#endif
+ si.lpAttributeList = heap_alloc(size);
+ ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ handle = OpenProcess(PROCESS_CREATE_PROCESS, TRUE, GetCurrentProcessId());
+ ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
+ &handle, sizeof(handle), NULL, NULL);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT,
+ NULL, NULL, (STARTUPINFOA *)&si, &info);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ CloseHandle(info.hThread);
+ CloseHandle(info.hProcess);
+ CloseHandle(handle);
+ pDeleteProcThreadAttributeList(si.lpAttributeList);
+ heap_free(si.lpAttributeList);
+
+ si.lpAttributeList = heap_alloc(size);
+ ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ handle = (HANDLE)0xdeadbeef;
+ ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
+ &handle, sizeof(handle), NULL, NULL);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT,
+ NULL, NULL, (STARTUPINFOA *)&si, &info);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %u.\n",
+ ret, GetLastError());
+ pDeleteProcThreadAttributeList(si.lpAttributeList);
+ heap_free(si.lpAttributeList);
+
+ si.lpAttributeList = heap_alloc(size);
+ ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ handle = NULL;
+ ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
+ &handle, sizeof(handle), NULL, NULL);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT,
+ NULL, NULL, (STARTUPINFOA *)&si, &info);
+ ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected ret %#x, GetLastError() %u.\n",
+ ret, GetLastError());
+ pDeleteProcThreadAttributeList(si.lpAttributeList);
+ heap_free(si.lpAttributeList);
+
+ si.lpAttributeList = heap_alloc(size);
+ ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ handle = GetCurrentProcess();
+ ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
+ &handle, sizeof(handle), NULL, NULL);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT,
+ NULL, NULL, (STARTUPINFOA *)&si, &info);
+ /* Broken on Vista / w7 / w10. */
+ ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_HANDLE),
+ "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+ if (ret)
+ {
+ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ CloseHandle(info.hThread);
+ CloseHandle(info.hProcess);
+ }
+ pDeleteProcThreadAttributeList(si.lpAttributeList);
+ heap_free(si.lpAttributeList);
+
si.lpAttributeList = heap_alloc(size);
ret = pInitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
--
2.23.0
Dec. 12, 2019
[PATCH v3 2/4] ntdll: Support creating processes with specified parent.
by Paul Gofman
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47817
Signed-off-by: Paul Gofman <gofmanp(a)gmail.com>
---
v2:
- don't use arbitrary thread as parent;
v3:
- don't check for current process pseudo handle value in RtlCreateUserProcess().
dlls/kernel32/tests/process.c | 4 ++--
dlls/ntdll/process.c | 5 +++--
include/wine/server_protocol.h | 4 +++-
server/console.c | 32 ++++++++++++++++----------------
server/process.c | 30 ++++++++++++++++++++++++------
server/process.h | 3 ++-
server/protocol.def | 1 +
server/request.h | 17 +++++++++--------
server/trace.c | 3 ++-
server/user.h | 3 ++-
server/winstation.c | 24 ++++++++++++++++--------
11 files changed, 80 insertions(+), 46 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 3efbfa2402..6d7a9a74c3 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -3874,14 +3874,14 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
memset(&parent_data, 0, sizeof(parent_data));
ret = ReadFile(read_pipe, &parent_data, sizeof(parent_data), &size, NULL);
- todo_wine_if(level == 2) ok((level == 2 && ret) || (level == 1 && !ret && GetLastError() == ERROR_INVALID_HANDLE),
+ ok((level == 2 && ret) || (level == 1 && !ret && GetLastError() == ERROR_INVALID_HANDLE),
"Got unexpected ret %#x, level %u, GetLastError() %u.\n",
ret, level, GetLastError());
}
if (level == 2)
{
- todo_wine ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n",
+ ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n",
parent_id, parent_data.parent_id);
return;
}
diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c
index 52d7ea429e..a4a2f17b4f 100644
--- a/dlls/ntdll/process.c
+++ b/dlls/ntdll/process.c
@@ -1667,8 +1667,8 @@ NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
RtlNormalizeProcessParams( params );
- TRACE( "%s image %s cmdline %s\n", debugstr_us( path ),
- debugstr_us( ¶ms->ImagePathName ), debugstr_us( ¶ms->CommandLine ));
+ TRACE("path %s, image %s, cmdline %s, parent %p.\n", debugstr_us(path),
+ debugstr_us(¶ms->ImagePathName), debugstr_us(¶ms->CommandLine), parent);
if ((status = get_pe_file_info( path, attributes, &file_handle, &pe_info )))
{
@@ -1709,6 +1709,7 @@ NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
SERVER_START_REQ( new_process )
{
+ req->parent_process = wine_server_obj_handle(parent);
req->inherit_all = inherit;
req->create_flags = params->DebugFlags; /* hack: creation flags stored in DebugFlags for now */
req->socket_fd = socketfd[1];
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index aaa5fd2e33..98ecd98b08 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -769,6 +769,7 @@ struct rawinput_device
struct new_process_request
{
struct request_header __header;
+ obj_handle_t parent_process;
int inherit_all;
unsigned int create_flags;
int socket_fd;
@@ -779,6 +780,7 @@ struct new_process_request
/* VARARG(objattr,object_attributes); */
/* VARARG(info,startup_info,info_size); */
/* VARARG(env,unicode_str); */
+ char __pad_44[4];
};
struct new_process_reply
{
@@ -6702,6 +6704,6 @@ union generic_reply
struct resume_process_reply resume_process_reply;
};
-#define SERVER_PROTOCOL_VERSION 593
+#define SERVER_PROTOCOL_VERSION 594
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/console.c b/server/console.c
index 59f8843a75..691a0bf05a 100644
--- a/server/console.c
+++ b/server/console.c
@@ -504,37 +504,37 @@ int free_console( struct process *process )
* 2/ parent is a renderer which launches process, and process should attach to the console
* rendered by parent
*/
-void inherit_console(struct thread *parent_thread, struct process *process, obj_handle_t hconin)
+void inherit_console(struct thread *parent_thread, struct process *parent, struct process *process,
+ obj_handle_t hconin)
{
int done = 0;
- struct process* parent = parent_thread->process;
/* if parent is a renderer, then attach current process to its console
* a bit hacky....
*/
- if (hconin)
+ if (hconin && parent_thread)
{
- struct console_input* console;
+ struct console_input *console;
/* FIXME: should we check some access rights ? */
- if ((console = (struct console_input*)get_handle_obj( parent, hconin,
- 0, &console_input_ops )))
- {
+ if ((console = (struct console_input *)get_handle_obj( parent, hconin,
+ 0, &console_input_ops )))
+ {
if (console->renderer == parent_thread)
- {
- process->console = (struct console_input*)grab_object( console );
- process->console->num_proc++;
- done = 1;
- }
- release_object( console );
- }
+ {
+ process->console = (struct console_input*)grab_object( console );
+ process->console->num_proc++;
+ done = 1;
+ }
+ release_object( console );
+ }
else clear_error(); /* ignore error */
}
/* otherwise, if parent has a console, attach child to this console */
if (!done && parent->console)
{
- process->console = (struct console_input*)grab_object( parent->console );
- process->console->num_proc++;
+ process->console = (struct console_input*)grab_object( parent->console );
+ process->console->num_proc++;
}
}
diff --git a/server/process.c b/server/process.c
index 16bb5d57e7..00ea45b068 100644
--- a/server/process.c
+++ b/server/process.c
@@ -1117,6 +1117,7 @@ DECL_HANDLER(new_process)
const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL );
struct process *process = NULL;
struct process *parent = current->process;
+ struct thread *parent_thread = current;
int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
if (socket_fd == -1)
@@ -1148,11 +1149,26 @@ DECL_HANDLER(new_process)
return;
}
+ if (req->parent_process)
+ {
+ if (!(parent = get_process_from_handle( req->parent_process, PROCESS_CREATE_PROCESS)))
+ {
+ set_error(STATUS_INVALID_HANDLE);
+ close(socket_fd);
+ return;
+ }
+ parent_thread = NULL;
+ }
+
if (parent->job && (req->create_flags & CREATE_BREAKAWAY_FROM_JOB) &&
!(parent->job->limit_flags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
{
set_error( STATUS_ACCESS_DENIED );
close( socket_fd );
+
+ if (req->parent_process)
+ release_object(parent);
+
return;
}
@@ -1222,7 +1238,7 @@ DECL_HANDLER(new_process)
}
/* connect to the window station */
- connect_process_winstation( process, current );
+ connect_process_winstation( process, parent_thread, parent );
/* set the process console */
if (!(req->create_flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)))
@@ -1231,7 +1247,7 @@ DECL_HANDLER(new_process)
* like if hConOut and hConIn are console handles, then they should be on the same
* physical console
*/
- inherit_console( current, process, req->inherit_all ? info->data->hstdin : 0 );
+ inherit_console( parent_thread, parent, process, req->inherit_all ? info->data->hstdin : 0 );
}
if (!req->inherit_all && !(req->create_flags & CREATE_NEW_CONSOLE))
@@ -1246,16 +1262,15 @@ DECL_HANDLER(new_process)
if (get_error() == STATUS_INVALID_HANDLE ||
get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error();
}
-
/* attach to the debugger if requested */
if (req->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
{
set_process_debugger( process, current );
process->debug_children = !(req->create_flags & DEBUG_ONLY_THIS_PROCESS);
}
- else if (parent->debugger && parent->debug_children)
+ else if (current->process->debugger && current->process->debug_children)
{
- set_process_debugger( process, parent->debugger );
+ set_process_debugger( process, current->process->debugger );
/* debug_children is set to 1 by default */
}
@@ -1265,9 +1280,12 @@ DECL_HANDLER(new_process)
info->process = (struct process *)grab_object( process );
reply->info = alloc_handle( current->process, info, SYNCHRONIZE, 0 );
reply->pid = get_process_id( process );
- reply->handle = alloc_handle_no_access_check( parent, process, req->access, objattr->attributes );
+ reply->handle = alloc_handle_no_access_check( current->process, process, req->access, objattr->attributes );
done:
+ if (req->parent_process)
+ release_object(parent);
+
if (process) release_object( process );
release_object( info );
}
diff --git a/server/process.h b/server/process.h
index 20ff6beda6..d8453eeaf2 100644
--- a/server/process.h
+++ b/server/process.h
@@ -141,7 +141,8 @@ extern struct process_snapshot *process_snap( int *count );
extern void enum_processes( int (*cb)(struct process*, void*), void *user);
/* console functions */
-extern void inherit_console(struct thread *parent_thread, struct process *process, obj_handle_t hconin);
+extern void inherit_console(struct thread *parent_thread, struct process *parent,
+ struct process *process, obj_handle_t hconin);
extern int free_console( struct process *process );
extern struct thread *console_get_renderer( struct console_input *console );
diff --git a/server/protocol.def b/server/protocol.def
index 1cb1fea602..7f9ec3a149 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -783,6 +783,7 @@ struct rawinput_device
/* Create a new process from the context of the parent */
@REQ(new_process)
+ obj_handle_t parent_process; /* parent process */
int inherit_all; /* inherit all handles from parent */
unsigned int create_flags; /* creation flags */
int socket_fd; /* file descriptor for process socket */
diff --git a/server/request.h b/server/request.h
index 90a3180a6c..9f36bcb711 100644
--- a/server/request.h
+++ b/server/request.h
@@ -745,14 +745,15 @@ C_ASSERT( sizeof(unsigned char) == 1 );
C_ASSERT( sizeof(unsigned int) == 4 );
C_ASSERT( sizeof(unsigned short) == 2 );
C_ASSERT( sizeof(user_handle_t) == 4 );
-C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 12 );
-C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 16 );
-C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 20 );
-C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 24 );
-C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 28 );
-C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 32 );
-C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 36 );
-C_ASSERT( sizeof(struct new_process_request) == 40 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, parent_process) == 12 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, inherit_all) == 16 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, create_flags) == 20 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, socket_fd) == 24 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 28 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 32 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 36 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 40 );
+C_ASSERT( sizeof(struct new_process_request) == 48 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, info) == 8 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, handle) == 16 );
diff --git a/server/trace.c b/server/trace.c
index 5b1d3ddea9..47f66b582c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1243,7 +1243,8 @@ typedef void (*dump_func)( const void *req );
static void dump_new_process_request( const struct new_process_request *req )
{
- fprintf( stderr, " inherit_all=%d", req->inherit_all );
+ fprintf( stderr, " parent_process=%04x", req->parent_process );
+ fprintf( stderr, ", inherit_all=%d", req->inherit_all );
fprintf( stderr, ", create_flags=%08x", req->create_flags );
fprintf( stderr, ", socket_fd=%d", req->socket_fd );
fprintf( stderr, ", exe_file=%04x", req->exe_file );
diff --git a/server/user.h b/server/user.h
index eb1b7ce1e4..35184d8780 100644
--- a/server/user.h
+++ b/server/user.h
@@ -183,7 +183,8 @@ extern client_ptr_t get_class_client_ptr( struct window_class *class );
extern struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle, unsigned int access );
extern struct winstation *get_process_winstation( struct process *process, unsigned int access );
extern struct desktop *get_thread_desktop( struct thread *thread, unsigned int access );
-extern void connect_process_winstation( struct process *process, struct thread *parent );
+extern void connect_process_winstation( struct process *process, struct thread *parent_thread,
+ struct process *parent_process );
extern void set_process_default_desktop( struct process *process, struct desktop *desktop,
obj_handle_t handle );
extern void close_process_desktop( struct process *process );
diff --git a/server/winstation.c b/server/winstation.c
index a09ca03e3b..f7932a9dc6 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -372,7 +372,8 @@ void set_process_default_desktop( struct process *process, struct desktop *deskt
}
/* connect a process to its window station */
-void connect_process_winstation( struct process *process, struct thread *parent )
+void connect_process_winstation( struct process *process, struct thread *parent_thread,
+ struct process *parent_process)
{
struct winstation *winstation = NULL;
struct desktop *desktop = NULL;
@@ -383,9 +384,9 @@ void connect_process_winstation( struct process *process, struct thread *parent
{
winstation = (struct winstation *)get_handle_obj( process, handle, 0, &winstation_ops );
}
- else if (parent && parent->process->winstation)
+ else if (parent_process->winstation)
{
- handle = duplicate_handle( parent->process, parent->process->winstation,
+ handle = duplicate_handle( parent_process, parent_process->winstation,
process, 0, 0, DUP_HANDLE_SAME_ACCESS );
winstation = (struct winstation *)get_handle_obj( process, handle, 0, &winstation_ops );
}
@@ -397,14 +398,21 @@ void connect_process_winstation( struct process *process, struct thread *parent
desktop = get_desktop_obj( process, handle, 0 );
if (!desktop || desktop->winstation != winstation) goto done;
}
- else if (parent && parent->desktop)
+ else
{
- desktop = get_desktop_obj( parent->process, parent->desktop, 0 );
+ if (parent_thread && parent_thread->desktop)
+ handle = parent_thread->desktop;
+ else if (parent_process->desktop)
+ handle = parent_process->desktop;
+ else
+ goto done;
+
+ desktop = get_desktop_obj( parent_process, handle, 0 );
+
if (!desktop || desktop->winstation != winstation) goto done;
- handle = duplicate_handle( parent->process, parent->desktop,
- process, 0, 0, DUP_HANDLE_SAME_ACCESS );
- }
+ handle = duplicate_handle( parent_process, handle, process, 0, 0, DUP_HANDLE_SAME_ACCESS );
+ }
if (handle) set_process_default_desktop( process, desktop, handle );
done:
--
2.23.0
Dec. 12, 2019