winehq.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
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
List overview
wine-commits
September 2021
----- 2025 -----
April 2025
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
January 2004
----- 2003 -----
December 2003
November 2003
October 2003
September 2003
August 2003
July 2003
June 2003
May 2003
April 2003
March 2003
February 2003
January 2003
----- 2002 -----
December 2002
November 2002
October 2002
September 2002
August 2002
July 2002
June 2002
May 2002
April 2002
March 2002
February 2002
January 2002
----- 2001 -----
December 2001
November 2001
October 2001
September 2001
August 2001
July 2001
June 2001
May 2001
April 2001
March 2001
February 2001
wine-commits@winehq.org
2 participants
1030 discussions
Start a n
N
ew thread
Nikolay Sivov : ole32/tests: Simplify test monikers creation helper.
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: 23390c9a358ac6bd64d72f2e526ae52f2f9880ca URL:
https://source.winehq.org/git/wine.git/?a=commit;h=23390c9a358ac6bd64d72f2e…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Fri Sep 24 15:51:44 2021 +0300 ole32/tests: Simplify test monikers creation helper. Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ole32/tests/moniker.c | 66 +++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 272c4e4c568..6b21a2e732e 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -127,33 +127,41 @@ static IMoniker *create_antimoniker(DWORD level) return moniker; } -static HRESULT create_moniker_from_desc(const char *desc, unsigned int *eaten, +static HRESULT create_moniker_parse_desc(const char *desc, unsigned int *eaten, IMoniker **moniker) { + unsigned int comp_len = 0; + WCHAR itemnameW[3] = L"Ix"; IMoniker *left, *right; - WCHAR nameW[3]; HRESULT hr; - desc += *eaten; - switch (*desc) { case 'I': - nameW[0] = desc[0]; - nameW[1] = desc[1]; - nameW[2] = 0; - *eaten += 2; - return CreateItemMoniker(L"!", nameW, moniker); + itemnameW[1] = desc[1]; + *eaten = 2; + return CreateItemMoniker(L"!", itemnameW, moniker); case 'A': - *eaten += 2; + *eaten = 2; *moniker = create_antimoniker(desc[1] - '0'); return S_OK; case 'C': - (*eaten)++; - hr = create_moniker_from_desc(desc, eaten, &left); + *eaten = 1; + desc++; + + comp_len = 0; + hr = create_moniker_parse_desc(desc, &comp_len, &left); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - hr = create_moniker_from_desc(desc, eaten, &right); + + *eaten += comp_len; + desc += comp_len; + + comp_len = 0; + hr = create_moniker_parse_desc(desc, &comp_len, &right); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + *eaten += comp_len; + hr = CreateGenericComposite(left, right, moniker); IMoniker_Release(left); IMoniker_Release(right); @@ -164,6 +172,12 @@ static HRESULT create_moniker_from_desc(const char *desc, unsigned int *eaten, } } +static HRESULT create_moniker_from_desc(const char *desc, IMoniker **moniker) +{ + unsigned int eaten = 0; + return create_moniker_parse_desc(desc, &eaten, moniker); +} + static SIZE_T round_global_size(SIZE_T size) { static SIZE_T global_size_alignment = -1; @@ -2642,8 +2656,7 @@ todo_wine /* Simplification has to through generic composite logic, even when resolved to non-composite, generic composite option has to be enabled. */ - eaten = 0; - hr = create_moniker_from_desc("CA1A3", &eaten, &c); + hr = create_moniker_from_desc("CA1A3", &c); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = IMoniker_ComposeWith(moniker, c, TRUE, &moniker2); ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr); @@ -2972,7 +2985,6 @@ static void test_generic_composite_moniker(void) IMoniker *moniker, *inverse, *moniker1, *moniker2; IEnumMoniker *enummoniker; IRunningObjectTable *rot; - unsigned int eaten, i; DWORD hash, cookie; HRESULT hr; IBindCtx *bindctx; @@ -2981,6 +2993,7 @@ static void test_generic_composite_moniker(void) IROTData *rotdata; IMarshal *marshal; IStream *stream; + unsigned int i; FILETIME ft; WCHAR *str; ULONG len; @@ -2991,16 +3004,14 @@ static void test_generic_composite_moniker(void) for (i = 0; i < ARRAY_SIZE(simplify_tests); ++i) { IMoniker *left, *right, *composite = NULL; - unsigned int moniker_type, eaten; + unsigned int moniker_type; WCHAR *name; winetest_push_context("simplify[%u]", i); - eaten = 0; - hr = create_moniker_from_desc(simplify_tests[i].left, &eaten, &left); + hr = create_moniker_from_desc(simplify_tests[i].left, &left); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - eaten = 0; - hr = create_moniker_from_desc(simplify_tests[i].right, &eaten, &right); + hr = create_moniker_from_desc(simplify_tests[i].right, &right); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = CreateGenericComposite(left, right, &composite); ok(hr == S_OK, "Failed to create a composite, hr %#x.\n", hr); @@ -3162,12 +3173,10 @@ todo_wine IMoniker_Release(moniker); /* GetTimeOfLastChange() */ - eaten = 0; - hr = create_moniker_from_desc("CI1I2", &eaten, &moniker); + hr = create_moniker_from_desc("CI1I2", &moniker); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - eaten = 0; - hr = create_moniker_from_desc("I1", &eaten, &moniker1); + hr = create_moniker_from_desc("I1", &moniker1); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); /* See if non-generic composition is possible */ @@ -3224,7 +3233,6 @@ static void test_pointer_moniker(void) IStream *stream; IROTData *rotdata; LPOLESTR display_name; - unsigned int eaten; IMarshal *marshal; LARGE_INTEGER pos; CLSID clsid; @@ -3417,8 +3425,7 @@ static void test_pointer_moniker(void) even when resolved to non-composite, generic composite option has to be enabled. */ /* P + (A,A3) -> A3 */ - eaten = 0; - hr = create_moniker_from_desc("CA1A3", &eaten, &c); + hr = create_moniker_from_desc("CA1A3", &c); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = IMoniker_ComposeWith(moniker, c, TRUE, &moniker2); ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr); @@ -3432,8 +3439,7 @@ static void test_pointer_moniker(void) IMoniker_Release(c); /* P + (A,I) -> I */ - eaten = 0; - hr = create_moniker_from_desc("CA1I1", &eaten, &c); + hr = create_moniker_from_desc("CA1I1", &c); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = IMoniker_ComposeWith(moniker, c, TRUE, &moniker2); ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr);
1
0
0
0
Nikolay Sivov : ole32/classmoniker: Always use generic composition in ComposeWith().
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: b7e4a5bcbd1357f908358dbf341f3d04e789876b URL:
https://source.winehq.org/git/wine.git/?a=commit;h=b7e4a5bcbd1357f908358dbf…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Fri Sep 24 15:51:43 2021 +0300 ole32/classmoniker: Always use generic composition in ComposeWith(). Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ole32/classmoniker.c | 78 +++++++---------------------------------------- 1 file changed, 11 insertions(+), 67 deletions(-) diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c index 03c7f773e29..8fe60c6ba71 100644 --- a/dlls/ole32/classmoniker.c +++ b/dlls/ole32/classmoniker.c @@ -298,79 +298,23 @@ static HRESULT WINAPI ClassMoniker_Reduce(IMoniker* iface, return MK_S_REDUCED_TO_SELF; } -/****************************************************************************** - * ClassMoniker_ComposeWith - ******************************************************************************/ -static HRESULT WINAPI ClassMoniker_ComposeWith(IMoniker* iface, - IMoniker* pmkRight, - BOOL fOnlyIfNotGeneric, - IMoniker** ppmkComposite) -{ - HRESULT res=S_OK; - DWORD mkSys,mkSys2; - IEnumMoniker* penumMk=0; - IMoniker *pmostLeftMk=0; - IMoniker* tempMkComposite=0; - - TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite); - - if ((ppmkComposite==NULL)||(pmkRight==NULL)) - return E_POINTER; - - *ppmkComposite=0; - - IMoniker_IsSystemMoniker(pmkRight,&mkSys); - - /* If pmkRight is an anti-moniker, the returned moniker is NULL */ - if(mkSys==MKSYS_ANTIMONIKER) - return res; - - else - /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ - /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ - if(mkSys==MKSYS_GENERICCOMPOSITE){ - - res=IMoniker_Enum(pmkRight,TRUE,&penumMk); - - if (FAILED(res)) - return res; - - res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL); - - IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2); - - if(mkSys2==MKSYS_ANTIMONIKER){ - - IMoniker_Release(pmostLeftMk); - - tempMkComposite=iface; - IMoniker_AddRef(iface); +static HRESULT WINAPI ClassMoniker_ComposeWith(IMoniker *iface, IMoniker *right, + BOOL only_if_not_generic, IMoniker **result) +{ + DWORD order; - while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){ + TRACE("%p, %p, %d, %p.\n", iface, right, only_if_not_generic, result); - res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite); + if (!result || !right) + return E_POINTER; - IMoniker_Release(tempMkComposite); - IMoniker_Release(pmostLeftMk); + *result = NULL; - tempMkComposite=*ppmkComposite; - IMoniker_AddRef(tempMkComposite); - } - return res; - } - else - return CreateGenericComposite(iface,pmkRight,ppmkComposite); - } - /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic - composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns - a NULL moniker and a return value of MK_E_NEEDGENERIC */ - else - if (!fOnlyIfNotGeneric) - return CreateGenericComposite(iface,pmkRight,ppmkComposite); + if (is_anti_moniker(right, &order)) + return S_OK; - else - return MK_E_NEEDGENERIC; + return only_if_not_generic ? MK_E_NEEDGENERIC : CreateGenericComposite(iface, right, result); } /******************************************************************************
1
0
0
0
Nikolay Sivov : ole32/pointermoniker: Always use generic composition in ComposeWith().
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: 59bf44b56943ee832798f3285ceeee8584ce34fd URL:
https://source.winehq.org/git/wine.git/?a=commit;h=59bf44b56943ee832798f328…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Fri Sep 24 15:51:42 2021 +0300 ole32/pointermoniker: Always use generic composition in ComposeWith(). Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ole32/pointermoniker.c | 79 +++++++-------------------------------------- dlls/ole32/tests/moniker.c | 33 ++++++++++++++++++- 2 files changed, 43 insertions(+), 69 deletions(-) diff --git a/dlls/ole32/pointermoniker.c b/dlls/ole32/pointermoniker.c index 34692c4965b..14cf8af9eaa 100644 --- a/dlls/ole32/pointermoniker.c +++ b/dlls/ole32/pointermoniker.c @@ -241,80 +241,23 @@ PointerMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, return MK_S_REDUCED_TO_SELF; } -/****************************************************************************** - * PointerMoniker_ComposeWith - ******************************************************************************/ -static HRESULT WINAPI -PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight, - BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) -{ - - HRESULT res=S_OK; - DWORD mkSys,mkSys2, order; - IEnumMoniker* penumMk=0; - IMoniker *pmostLeftMk=0; - IMoniker* tempMkComposite=0; - - TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite); - if ((ppmkComposite==NULL)||(pmkRight==NULL)) - return E_POINTER; - - *ppmkComposite=0; - - if (is_anti_moniker(pmkRight, &order)) - { - return order > 1 ? create_anti_moniker(order - 1, ppmkComposite) : S_OK; - } - else - { - /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ - /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ - IMoniker_IsSystemMoniker(pmkRight,&mkSys); - - if(mkSys==MKSYS_GENERICCOMPOSITE){ - - res=IMoniker_Enum(pmkRight,TRUE,&penumMk); - - if (FAILED(res)) - return res; - - res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL); - - IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2); - - if(mkSys2==MKSYS_ANTIMONIKER){ - - IMoniker_Release(pmostLeftMk); - - tempMkComposite=iface; - IMoniker_AddRef(iface); +static HRESULT WINAPI PointerMonikerImpl_ComposeWith(IMoniker *iface, IMoniker *right, + BOOL only_if_not_generic, IMoniker **result) +{ + DWORD order; - while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){ + TRACE("%p, %p, %d, %p.\n", iface, right, only_if_not_generic, result); - res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite); + if (!result || !right) + return E_POINTER; - IMoniker_Release(tempMkComposite); - IMoniker_Release(pmostLeftMk); + *result = NULL; - tempMkComposite=*ppmkComposite; - IMoniker_AddRef(tempMkComposite); - } - return res; - } - else - return CreateGenericComposite(iface,pmkRight,ppmkComposite); - } - /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic - composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns - a NULL moniker and a return value of MK_E_NEEDGENERIC */ - else - if (!fOnlyIfNotGeneric) - return CreateGenericComposite(iface,pmkRight,ppmkComposite); + if (is_anti_moniker(right, &order)) + return order > 1 ? create_anti_moniker(order - 1, result) : S_OK; - else - return MK_E_NEEDGENERIC; - } + return only_if_not_generic ? MK_E_NEEDGENERIC : CreateGenericComposite(iface, right, result); } /****************************************************************************** diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 1b44c80fe45..272c4e4c568 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -3213,7 +3213,7 @@ todo_wine static void test_pointer_moniker(void) { - IMoniker *moniker, *moniker2, *prefix, *inverse, *anti; + IMoniker *moniker, *moniker2, *prefix, *inverse, *anti, *c; struct test_factory factory; IEnumMoniker *enummoniker; DWORD hash, size; @@ -3224,6 +3224,7 @@ static void test_pointer_moniker(void) IStream *stream; IROTData *rotdata; LPOLESTR display_name; + unsigned int eaten; IMarshal *marshal; LARGE_INTEGER pos; CLSID clsid; @@ -3412,6 +3413,36 @@ static void test_pointer_moniker(void) IMoniker_Release(anti); + /* Simplification has to through generic composite logic, + even when resolved to non-composite, generic composite option has to be enabled. */ + + /* P + (A,A3) -> A3 */ + eaten = 0; + hr = create_moniker_from_desc("CA1A3", &eaten, &c); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMoniker_ComposeWith(moniker, c, TRUE, &moniker2); + ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr); + hr = IMoniker_ComposeWith(moniker, c, FALSE, &moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER); + hr = IMoniker_Hash(moniker2, &hash); + ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr); + ok(hash == 0x80000003, "Unexpected hash.\n"); + IMoniker_Release(moniker2); + IMoniker_Release(c); + + /* P + (A,I) -> I */ + eaten = 0; + hr = create_moniker_from_desc("CA1I1", &eaten, &c); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMoniker_ComposeWith(moniker, c, TRUE, &moniker2); + ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr); + hr = IMoniker_ComposeWith(moniker, c, FALSE, &moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + TEST_MONIKER_TYPE(moniker2, MKSYS_ITEMMONIKER); + IMoniker_Release(moniker2); + IMoniker_Release(c); + IMoniker_Release(moniker); }
1
0
0
0
Nikolay Sivov : ole32/itemmoniker: Always use generic composition in ComposeWith().
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: 7bf6fb787c2df2fd1ba95ba4d7eff18c171b5c1b URL:
https://source.winehq.org/git/wine.git/?a=commit;h=7bf6fb787c2df2fd1ba95ba4…
Author: Nikolay Sivov <nsivov(a)codeweavers.com> Date: Fri Sep 24 15:51:41 2021 +0300 ole32/itemmoniker: Always use generic composition in ComposeWith(). Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ole32/itemmoniker.c | 76 ++++++------------------------------ dlls/ole32/tests/moniker.c | 97 +++++++++++++++++++++++++++------------------- 2 files changed, 68 insertions(+), 105 deletions(-) diff --git a/dlls/ole32/itemmoniker.c b/dlls/ole32/itemmoniker.c index c42cc75c224..770b042aac7 100644 --- a/dlls/ole32/itemmoniker.c +++ b/dlls/ole32/itemmoniker.c @@ -511,77 +511,23 @@ static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface, return MK_S_REDUCED_TO_SELF; } -/****************************************************************************** - * ItemMoniker_ComposeWith - ******************************************************************************/ -static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface, - IMoniker* pmkRight, - BOOL fOnlyIfNotGeneric, - IMoniker** ppmkComposite) -{ - HRESULT res=S_OK; - DWORD mkSys,mkSys2, order; - IEnumMoniker* penumMk=0; - IMoniker *pmostLeftMk=0; - IMoniker* tempMkComposite=0; - - TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite); - - if ((ppmkComposite==NULL)||(pmkRight==NULL)) - return E_POINTER; - - *ppmkComposite=0; - - if (is_anti_moniker(pmkRight, &order)) - { - return order > 1 ? create_anti_moniker(order - 1, ppmkComposite) : S_OK; - } - else - /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ - /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ - IMoniker_IsSystemMoniker(pmkRight,&mkSys); - if(mkSys==MKSYS_GENERICCOMPOSITE){ - - res=IMoniker_Enum(pmkRight,TRUE,&penumMk); - - if (FAILED(res)) - return res; - - res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL); - - IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2); - if(mkSys2==MKSYS_ANTIMONIKER){ - - IMoniker_Release(pmostLeftMk); +static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker *iface, IMoniker *right, + BOOL only_if_not_generic, IMoniker **result) +{ + DWORD order; - tempMkComposite=iface; - IMoniker_AddRef(iface); + TRACE("%p, %p, %d, %p\n", iface, right, only_if_not_generic, result); - while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){ + if (!result || !right) + return E_POINTER; - res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite); + *result = NULL; - IMoniker_Release(tempMkComposite); - IMoniker_Release(pmostLeftMk); + if (is_anti_moniker(right, &order)) + return order > 1 ? create_anti_moniker(order - 1, result) : S_OK; - tempMkComposite=*ppmkComposite; - IMoniker_AddRef(tempMkComposite); - } - return res; - } - else - return CreateGenericComposite(iface,pmkRight,ppmkComposite); - } - /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic - composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns - a NULL moniker and a return value of MK_E_NEEDGENERIC */ - else - if (!fOnlyIfNotGeneric) - return CreateGenericComposite(iface,pmkRight,ppmkComposite); - - else - return MK_E_NEEDGENERIC; + return only_if_not_generic ? MK_E_NEEDGENERIC : CreateGenericComposite(iface, right, result); } /****************************************************************************** diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 4d40dcb6e4b..1b44c80fe45 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -127,6 +127,43 @@ static IMoniker *create_antimoniker(DWORD level) return moniker; } +static HRESULT create_moniker_from_desc(const char *desc, unsigned int *eaten, + IMoniker **moniker) +{ + IMoniker *left, *right; + WCHAR nameW[3]; + HRESULT hr; + + desc += *eaten; + + switch (*desc) + { + case 'I': + nameW[0] = desc[0]; + nameW[1] = desc[1]; + nameW[2] = 0; + *eaten += 2; + return CreateItemMoniker(L"!", nameW, moniker); + case 'A': + *eaten += 2; + *moniker = create_antimoniker(desc[1] - '0'); + return S_OK; + case 'C': + (*eaten)++; + hr = create_moniker_from_desc(desc, eaten, &left); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = create_moniker_from_desc(desc, eaten, &right); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = CreateGenericComposite(left, right, moniker); + IMoniker_Release(left); + IMoniker_Release(right); + return hr; + default: + ok(0, "Unexpected description %s.\n", desc); + return E_NOTIMPL; + } +} + static SIZE_T round_global_size(SIZE_T size) { static SIZE_T global_size_alignment = -1; @@ -2267,7 +2304,7 @@ static void test_item_moniker(void) "Moniker_IsRunning", NULL }; - IMoniker *moniker, *moniker2, *moniker3, *reduced, *anti, *inverse; + IMoniker *moniker, *moniker2, *moniker3, *reduced, *anti, *inverse, *c; DWORD i, hash, eaten, cookie; HRESULT hr; IBindCtx *bindctx; @@ -2589,7 +2626,7 @@ todo_wine ok(!moniker2, "Unexpected pointer.\n"); IMoniker_Release(anti); - /* I + A2 -> (A) */ + /* I + A2 -> A */ anti = create_antimoniker(2); hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); @@ -2601,6 +2638,24 @@ todo_wine IMoniker_Release(anti); + /* I + (A,A3) -> A3 */ + + /* Simplification has to through generic composite logic, + even when resolved to non-composite, generic composite option has to be enabled. */ + eaten = 0; + hr = create_moniker_from_desc("CA1A3", &eaten, &c); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMoniker_ComposeWith(moniker, c, TRUE, &moniker2); + ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr); + hr = IMoniker_ComposeWith(moniker, c, FALSE, &moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER); + hr = IMoniker_Hash(moniker2, &hash); + ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr); + ok(hash == 0x80000003, "Unexpected hash.\n"); + IMoniker_Release(moniker2); + IMoniker_Release(c); + IMoniker_Release(moniker); /* CommonPrefixWith */ @@ -2893,43 +2948,6 @@ todo_wine IMoniker_Release(moniker2); } -static HRESULT create_moniker_from_desc(const char *desc, unsigned int *eaten, - IMoniker **moniker) -{ - IMoniker *left, *right; - WCHAR nameW[3]; - HRESULT hr; - - desc += *eaten; - - switch (*desc) - { - case 'I': - nameW[0] = desc[0]; - nameW[1] = desc[1]; - nameW[2] = 0; - *eaten += 2; - return CreateItemMoniker(L"!", nameW, moniker); - case 'A': - *eaten += 2; - *moniker = create_antimoniker(desc[1] - '0'); - return S_OK; - case 'C': - (*eaten)++; - hr = create_moniker_from_desc(desc, eaten, &left); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - hr = create_moniker_from_desc(desc, eaten, &right); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - hr = CreateGenericComposite(left, right, moniker); - IMoniker_Release(left); - IMoniker_Release(right); - return hr; - default: - ok(0, "Unexpected description %s.\n", desc); - return E_NOTIMPL; - } -} - static void test_generic_composite_moniker(void) { static const struct simplify_test @@ -3154,7 +3172,6 @@ todo_wine /* See if non-generic composition is possible */ hr = IMoniker_ComposeWith(moniker1, moniker, TRUE, &moniker2); -todo_wine ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr); hr = IBindCtx_GetRunningObjectTable(bindctx, &rot);
1
0
0
0
Rémi Bernon : winebus.sys: Add haptics rumble support for UDEV lnxev devices.
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: a27708dc9b4cf9c6529aa0bc5b391ed43b1cb5a7 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=a27708dc9b4cf9c6529aa0bc…
Author: Rémi Bernon <rbernon(a)codeweavers.com> Date: Fri Sep 24 11:51:57 2021 +0200 winebus.sys: Add haptics rumble support for UDEV lnxev devices. Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winebus.sys/bus_udev.c | 62 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 8bc9b4bf64d..88db78360e2 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -126,6 +126,8 @@ struct lnxev_device BYTE rel_map[HID_REL_MAX]; BYTE hat_map[8]; BYTE button_map[KEY_MAX]; + + int haptic_effect_id; }; static inline struct base_device *impl_from_unix_device(struct unix_device *iface) @@ -372,6 +374,8 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d struct input_absinfo abs_info[HID_ABS_MAX]; BYTE absbits[(ABS_MAX+7)/8]; BYTE relbits[(REL_MAX+7)/8]; + BYTE ffbits[(FF_MAX+7)/8]; + struct ff_effect effect; USAGE_AND_PAGE usage; INT i, button_count, abs_count, rel_count, hat_count; const BYTE *device_usage = what_am_I(dev); @@ -387,6 +391,11 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno, strerror(errno)); memset(absbits, 0, sizeof(absbits)); } + if (ioctl(impl->base.device_fd, EVIOCGBIT(EV_FF, sizeof(ffbits)), ffbits) == -1) + { + WARN("ioctl(EVIOCGBIT, EV_FF) failed: %d %s\n", errno, strerror(errno)); + memset(ffbits, 0, sizeof(ffbits)); + } if (!hid_device_begin_report_descriptor(iface, device_usage[0], device_usage[1])) return STATUS_NO_MEMORY; @@ -443,6 +452,23 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d if (!hid_device_end_input_report(iface)) return STATUS_NO_MEMORY; + impl->haptic_effect_id = -1; + if (test_bit(ffbits, FF_RUMBLE)) + { + effect.id = -1; + effect.type = FF_RUMBLE; + effect.replay.length = 0; + effect.u.rumble.strong_magnitude = 0; + effect.u.rumble.weak_magnitude = 0; + + if (ioctl(impl->base.device_fd, EVIOCSFF, &effect) == -1) + WARN("couldn't allocate rumble effect for haptics: %d %s\n", errno, strerror(errno)); + else if (!hid_device_add_haptics(iface)) + return FALSE; + else + impl->haptic_effect_id = effect.id; + } + if (!hid_device_end_report_descriptor(iface)) return STATUS_NO_MEMORY; @@ -737,10 +763,42 @@ static void lnxev_device_read_report(struct unix_device *iface) static NTSTATUS lnxev_device_haptics_start(struct unix_device *iface, DWORD duration_ms, USHORT rumble_intensity, USHORT buzz_intensity) { - FIXME("iface %p, duration_ms %u, rumble_intensity %u, buzz_intensity %u stub!\n", iface, + struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); + struct ff_effect effect = + { + .id = impl->haptic_effect_id, + .type = FF_RUMBLE, + }; + struct input_event event; + + TRACE("iface %p, duration_ms %u, rumble_intensity %u, buzz_intensity %u stub!\n", iface, duration_ms, rumble_intensity, buzz_intensity); - return STATUS_NOT_IMPLEMENTED; + effect.replay.length = duration_ms; + effect.u.rumble.strong_magnitude = rumble_intensity; + effect.u.rumble.weak_magnitude = buzz_intensity; + + if (ioctl(impl->base.device_fd, EVIOCSFF, &effect) == -1) + { + effect.id = -1; + if (ioctl(impl->base.device_fd, EVIOCSFF, &effect) == 1) + { + WARN("couldn't re-allocate rumble effect for haptics: %d %s\n", errno, strerror(errno)); + return STATUS_UNSUCCESSFUL; + } + impl->haptic_effect_id = effect.id; + } + + event.type = EV_FF; + event.code = effect.id; + event.value = 1; + if (write(impl->base.device_fd, &event, sizeof(event)) == -1) + { + WARN("couldn't start haptics rumble effect: %d %s\n", errno, strerror(errno)); + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; } static const struct hid_device_vtbl lnxev_device_vtbl =
1
0
0
0
Rémi Bernon : winebus.sys: Remove old vendor rumble report.
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: e42f11d7a23be129a04c0be6647e76eb309ddfd5 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=e42f11d7a23be129a04c0be6…
Author: Rémi Bernon <rbernon(a)codeweavers.com> Date: Fri Sep 24 11:51:56 2021 +0200 winebus.sys: Remove old vendor rumble report. Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winebus.sys/hid.c | 40 +--------------------------------------- dlls/winebus.sys/unix_private.h | 1 - 2 files changed, 1 insertion(+), 40 deletions(-) diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 2a02a660f03..0c8e85dfc5f 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -317,32 +317,6 @@ BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page BOOL hid_device_add_haptics(struct unix_device *iface) { struct hid_report_descriptor *desc = &iface->hid_report_descriptor; - const BYTE vendor_report = ++desc->next_report_id[HidP_Output]; - const BYTE vendor_template[] = - { - USAGE_PAGE(2, HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN), - COLLECTION(1, Report), - REPORT_ID(1, vendor_report), - /* padding */ - REPORT_COUNT(1, 0x02), - REPORT_SIZE(1, 0x08), - OUTPUT(1, Data|Var|Abs), - /* actuators */ - USAGE(1, 0x01), - LOGICAL_MINIMUM(1, 0x00), - LOGICAL_MAXIMUM(1, 0xff), - PHYSICAL_MINIMUM(1, 0x00), - PHYSICAL_MAXIMUM(1, 0xff), - REPORT_SIZE(1, 0x08), - REPORT_COUNT(1, 0x02), - OUTPUT(1, Data|Var|Abs), - /* padding */ - REPORT_COUNT(1, 0x02), - REPORT_SIZE(1, 0x08), - OUTPUT(1, Data|Var|Abs), - END_COLLECTION, - }; - const BYTE haptics_features_report = ++desc->next_report_id[HidP_Feature]; const BYTE haptics_waveform_report = ++desc->next_report_id[HidP_Output]; const BYTE haptics_template[] = @@ -409,8 +383,6 @@ BOOL hid_device_add_haptics(struct unix_device *iface) END_COLLECTION, }; - iface->hid_haptics.vendor_report = vendor_report; - iface->hid_haptics.features_report = haptics_features_report; iface->hid_haptics.waveform_report = haptics_waveform_report; iface->hid_haptics.features.waveform_list[0] = HID_USAGE_HAPTICS_WAVEFORM_RUMBLE; @@ -419,9 +391,6 @@ BOOL hid_device_add_haptics(struct unix_device *iface) iface->hid_haptics.features.duration_list[1] = 0; iface->hid_haptics.features.waveform_cutoff_time_ms = 1000; - if (!hid_report_descriptor_append(desc, vendor_template, sizeof(vendor_template))) - return FALSE; - return hid_report_descriptor_append(desc, haptics_template, sizeof(haptics_template)); } @@ -457,15 +426,8 @@ NTSTATUS hid_device_get_report_descriptor(struct unix_device *iface, BYTE *buffe static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) { struct hid_haptics *haptics = &iface->hid_haptics; - if (packet->reportId == haptics->vendor_report) - { - WORD left = packet->reportBuffer[2] * 128; - WORD right = packet->reportBuffer[3] * 128; - io->Information = packet->reportBufferLen; - io->Status = iface->hid_vtbl->haptics_start(iface, -1, left, right); - } - else if (packet->reportId == haptics->waveform_report) + if (packet->reportId == haptics->waveform_report) { struct hid_haptics_waveform *waveform = (struct hid_haptics_waveform *)(packet->reportBuffer + 1); struct hid_haptics_waveform *rumble = haptics->waveforms + HAPTICS_WAVEFORM_RUMBLE_INDEX; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index 5da5ca58e7f..01638bf19fc 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -83,7 +83,6 @@ struct hid_haptics { struct hid_haptics_features features; struct hid_haptics_waveform waveforms[HAPTICS_WAVEFORM_LAST_INDEX + 1]; - BYTE vendor_report; BYTE features_report; BYTE waveform_report; };
1
0
0
0
Rémi Bernon : xinput1_3: Use new HID haptics rumble report.
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: 36749a8f7da392429c7f4a8e3de0241df5cd06e4 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=36749a8f7da392429c7f4a8e…
Author: Rémi Bernon <rbernon(a)codeweavers.com> Date: Fri Sep 24 11:51:55 2021 +0200 xinput1_3: Use new HID haptics rumble report. Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=51587
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/xinput1_3/main.c | 135 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 26 deletions(-) diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c index d601c23f6f1..2881a370534 100644 --- a/dlls/xinput1_3/main.c +++ b/dlls/xinput1_3/main.c @@ -77,6 +77,11 @@ struct xinput_controller char *input_report_buf; char *output_report_buf; + char *feature_report_buf; + + BYTE haptics_report; + BYTE haptics_rumble_index; + BYTE haptics_buzz_index; } hid; }; @@ -153,14 +158,17 @@ static void check_value_caps(struct xinput_controller *controller, USHORT usage, } } -static BOOL controller_check_caps(struct xinput_controller *controller, PHIDP_PREPARSED_DATA preparsed) +static BOOL controller_check_caps(struct xinput_controller *controller, HANDLE device, PHIDP_PREPARSED_DATA preparsed) { + ULONG collections_count = 0, report_len = controller->hid.caps.FeatureReportByteLength; + char *report_buf = controller->hid.feature_report_buf; XINPUT_CAPABILITIES *caps = &controller->caps; + HIDP_VALUE_CAPS *value_caps, waveform_cap; + int i, u, waveform_list, button_count = 0; + HIDP_LINK_COLLECTION_NODE *collections; HIDP_BUTTON_CAPS *button_caps; - HIDP_VALUE_CAPS *value_caps; + USHORT caps_count = 0; NTSTATUS status; - int i, u; - int button_count = 0; /* Count buttons */ memset(caps, 0, sizeof(XINPUT_CAPABILITIES)); @@ -210,11 +218,66 @@ static BOOL controller_check_caps(struct xinput_controller *controller, PHIDP_PR caps->Type = XINPUT_DEVTYPE_GAMEPAD; caps->SubType = XINPUT_DEVSUBTYPE_GAMEPAD; - if (controller->hid.caps.NumberOutputValueCaps > 0) + collections_count = controller->hid.caps.NumberLinkCollectionNodes; + if (!(collections = malloc(sizeof(*collections) * controller->hid.caps.NumberLinkCollectionNodes))) return FALSE; + status = HidP_GetLinkCollectionNodes(collections, &collections_count, preparsed); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetLinkCollectionNodes returned %#x\n", status); + else for (i = 0; i < collections_count; ++i) + { + if (collections[i].LinkUsagePage != HID_USAGE_PAGE_HAPTICS) continue; + if (collections[i].LinkUsage == HID_USAGE_HAPTICS_WAVEFORM_LIST) break; + } + free(collections); + if (status != HIDP_STATUS_SUCCESS || i == collections_count) + { + WARN("could not find haptics waveform list collection\n"); + return TRUE; + } + waveform_list = i; + + caps_count = 1; + status = HidP_GetSpecificValueCaps(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &waveform_cap, &caps_count, preparsed); + if (status != HIDP_STATUS_SUCCESS || !caps_count) + { + WARN("could not find haptics waveform list report id, status %#x\n", status); + return TRUE; + } + + status = HidP_InitializeReportForID(HidP_Feature, waveform_cap.ReportID, preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_InitializeReportForID returned %#x\n", status); + if (!HidD_GetFeature(device, report_buf, report_len)) + { + WARN("failed to get waveform list report, error %u\n", GetLastError()); + return TRUE; + } + + controller->hid.haptics_buzz_index = 0; + controller->hid.haptics_rumble_index = 0; + for (i = 3; status == HIDP_STATUS_SUCCESS; ++i) + { + ULONG waveform = 0; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, + i, &waveform, preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue returned %#x\n", status); + else if (waveform == HID_USAGE_HAPTICS_WAVEFORM_BUZZ) controller->hid.haptics_buzz_index = i; + else if (waveform == HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) controller->hid.haptics_rumble_index = i; + } + + if (!controller->hid.haptics_buzz_index) WARN("haptics buzz not supported\n"); + if (!controller->hid.haptics_rumble_index) WARN("haptics rumble not supported\n"); + if (!controller->hid.haptics_rumble_index && !controller->hid.haptics_buzz_index) return TRUE; + + caps_count = 1; + status = HidP_GetSpecificValueCaps(HidP_Output, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_MANUAL_TRIGGER, + &waveform_cap, &caps_count, preparsed); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetSpecificValueCaps MANUAL_TRIGGER returned %#x\n", status); + else if (!caps_count) WARN("haptics manual trigger not supported\n"); + else { caps->Flags |= XINPUT_CAPS_FFB_SUPPORTED; caps->Vibration.wLeftMotorSpeed = 255; caps->Vibration.wRightMotorSpeed = 255; + controller->hid.haptics_report = waveform_cap.ReportID; } return TRUE; @@ -222,30 +285,47 @@ static BOOL controller_check_caps(struct xinput_controller *controller, PHIDP_PR static DWORD HID_set_state(struct xinput_controller *controller, XINPUT_VIBRATION *state) { - char *output_report_buf = controller->hid.output_report_buf; - ULONG output_report_len = controller->hid.caps.OutputReportByteLength; + ULONG report_len = controller->hid.caps.OutputReportByteLength; + PHIDP_PREPARSED_DATA preparsed = controller->hid.preparsed; + char *report_buf = controller->hid.output_report_buf; + BYTE report_id = controller->hid.haptics_report; + NTSTATUS status; - if (controller->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED) - { - controller->vibration.wLeftMotorSpeed = state->wLeftMotorSpeed; - controller->vibration.wRightMotorSpeed = state->wRightMotorSpeed; + if (!(controller->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)) return ERROR_SUCCESS; - if (controller->enabled) - { - memset(output_report_buf, 0, output_report_len); - output_report_buf[0] = 1; - output_report_buf[1] = 0x8; - output_report_buf[3] = (BYTE)(state->wLeftMotorSpeed / 256); - output_report_buf[4] = (BYTE)(state->wRightMotorSpeed / 256); + controller->vibration.wLeftMotorSpeed = state->wLeftMotorSpeed; + controller->vibration.wRightMotorSpeed = state->wRightMotorSpeed; - if (!HidD_SetOutputReport(controller->device, output_report_buf, output_report_len)) - { - WARN("unable to set output report, HidD_SetOutputReport failed with error %u\n", GetLastError()); - return GetLastError(); - } + if (!controller->enabled) return ERROR_SUCCESS; - return ERROR_SUCCESS; - } + /* send haptics rumble report (left motor) */ + status = HidP_InitializeReportForID(HidP_Output, report_id, preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_InitializeReportForID returned %#x\n", status); + status = HidP_SetUsageValue(HidP_Output, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_INTENSITY, + state->wLeftMotorSpeed, preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_SetUsageValue INTENSITY returned %#x\n", status); + status = HidP_SetUsageValue(HidP_Output, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_MANUAL_TRIGGER, + controller->hid.haptics_rumble_index, preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_SetUsageValue MANUAL_TRIGGER returned %#x\n", status); + if (!HidD_SetOutputReport(controller->device, report_buf, report_len)) + { + WARN("HidD_SetOutputReport failed with error %u\n", GetLastError()); + return GetLastError(); + } + + /* send haptics buzz report (right motor) */ + status = HidP_InitializeReportForID(HidP_Output, report_id, preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_InitializeReportForID returned %#x\n", status); + status = HidP_SetUsageValue(HidP_Output, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_INTENSITY, + state->wRightMotorSpeed, preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_SetUsageValue INTENSITY returned %#x\n", status); + status = HidP_SetUsageValue(HidP_Output, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_MANUAL_TRIGGER, + controller->hid.haptics_buzz_index, preparsed, report_buf, report_len); + if (status != HIDP_STATUS_SUCCESS) WARN("HidP_SetUsageValue MANUAL_TRIGGER returned %#x\n", status); + if (!HidD_SetOutputReport(controller->device, report_buf, report_len)) + { + WARN("HidD_SetOutputReport failed with error %u\n", GetLastError()); + return GetLastError(); } return ERROR_SUCCESS; @@ -283,7 +363,8 @@ static BOOL controller_init(struct xinput_controller *controller, PHIDP_PREPARSE HANDLE event = NULL; controller->hid.caps = *caps; - if (!controller_check_caps(controller, preparsed)) goto failed; + if (!(controller->hid.feature_report_buf = calloc(1, controller->hid.caps.FeatureReportByteLength))) goto failed; + if (!controller_check_caps(controller, device, preparsed)) goto failed; if (!(event = CreateEventA(NULL, FALSE, FALSE, NULL))) goto failed; TRACE("Found gamepad %s\n", debugstr_w(device_path)); @@ -307,6 +388,7 @@ static BOOL controller_init(struct xinput_controller *controller, PHIDP_PREPARSE failed: free(controller->hid.input_report_buf); free(controller->hid.output_report_buf); + free(controller->hid.feature_report_buf); memset(&controller->hid, 0, sizeof(controller->hid)); CloseHandle(event); return FALSE; @@ -379,6 +461,7 @@ static void controller_destroy(struct xinput_controller *controller) free(controller->hid.input_report_buf); free(controller->hid.output_report_buf); + free(controller->hid.feature_report_buf); HidD_FreePreparsedData(controller->hid.preparsed); memset(&controller->hid, 0, sizeof(controller->hid)); }
1
0
0
0
Rémi Bernon : winebus.sys: Add a new rumble report using HID haptics.
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: cb4d378fa9d3b264357b0bf19f6980f40d81d67e URL:
https://source.winehq.org/git/wine.git/?a=commit;h=cb4d378fa9d3b264357b0bf1…
Author: Rémi Bernon <rbernon(a)codeweavers.com> Date: Fri Sep 24 11:51:54 2021 +0200 winebus.sys: Add a new rumble report using HID haptics. Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winebus.sys/hid.c | 150 +++++++++++++++++++++++++++++++++++++--- dlls/winebus.sys/unix_private.h | 26 +++++++ 2 files changed, 167 insertions(+), 9 deletions(-) diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index c1dd75f77c4..2a02a660f03 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -24,6 +24,7 @@ #include <stdarg.h> #include <stdlib.h> +#include <assert.h> #include "ntstatus.h" #define WIN32_NO_STATUS @@ -316,12 +317,12 @@ BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page BOOL hid_device_add_haptics(struct unix_device *iface) { struct hid_report_descriptor *desc = &iface->hid_report_descriptor; - const BYTE report_id = ++desc->next_report_id[HidP_Output]; - const BYTE template[] = + const BYTE vendor_report = ++desc->next_report_id[HidP_Output]; + const BYTE vendor_template[] = { USAGE_PAGE(2, HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN), COLLECTION(1, Report), - REPORT_ID(1, report_id), + REPORT_ID(1, vendor_report), /* padding */ REPORT_COUNT(1, 0x02), REPORT_SIZE(1, 0x08), @@ -342,8 +343,86 @@ BOOL hid_device_add_haptics(struct unix_device *iface) END_COLLECTION, }; - iface->hid_haptics.vendor_report = report_id; - return hid_report_descriptor_append(desc, template, sizeof(template)); + const BYTE haptics_features_report = ++desc->next_report_id[HidP_Feature]; + const BYTE haptics_waveform_report = ++desc->next_report_id[HidP_Output]; + const BYTE haptics_template[] = + { + USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), + USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER), + COLLECTION(1, Logical), + REPORT_ID(1, haptics_features_report), + + USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_LIST), + COLLECTION(1, NamedArray), + USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL), + USAGE(1, 3), /* HID_USAGE_HAPTICS_WAVEFORM_RUMBLE */ + USAGE(1, 4), /* HID_USAGE_HAPTICS_WAVEFORM_BUZZ */ + REPORT_COUNT(1, 2), + REPORT_SIZE(1, 16), + FEATURE(1, Data|Var|Abs|Null), + END_COLLECTION, + + USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), + USAGE(1, HID_USAGE_HAPTICS_DURATION_LIST), + COLLECTION(1, NamedArray), + USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL), + USAGE(1, 3), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) */ + USAGE(1, 4), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_BUZZ) */ + REPORT_COUNT(1, 2), + REPORT_SIZE(1, 16), + FEATURE(1, Data|Var|Abs|Null), + END_COLLECTION, + + USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), + USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME), + UNIT(2, 0x1001), /* seconds */ + UNIT_EXPONENT(1, -3), /* 10^-3 */ + LOGICAL_MINIMUM(4, 0x00000000), + LOGICAL_MAXIMUM(4, 0x7fffffff), + PHYSICAL_MINIMUM(4, 0x00000000), + PHYSICAL_MAXIMUM(4, 0x7fffffff), + REPORT_SIZE(1, 32), + REPORT_COUNT(1, 1), + FEATURE(1, Data|Var|Abs), + /* reset global items */ + UNIT(1, 0), /* None */ + UNIT_EXPONENT(1, 0), + + REPORT_ID(1, haptics_waveform_report), + USAGE(1, HID_USAGE_HAPTICS_MANUAL_TRIGGER), + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(1, 4), + PHYSICAL_MINIMUM(1, 1), + PHYSICAL_MAXIMUM(1, 4), + REPORT_SIZE(1, 16), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs), + + USAGE(1, HID_USAGE_HAPTICS_INTENSITY), + LOGICAL_MINIMUM(4, 0x00000000), + LOGICAL_MAXIMUM(4, 0x0000ffff), + PHYSICAL_MINIMUM(4, 0x00000000), + PHYSICAL_MAXIMUM(4, 0x0000ffff), + REPORT_SIZE(1, 16), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs), + END_COLLECTION, + }; + + iface->hid_haptics.vendor_report = vendor_report; + + iface->hid_haptics.features_report = haptics_features_report; + iface->hid_haptics.waveform_report = haptics_waveform_report; + iface->hid_haptics.features.waveform_list[0] = HID_USAGE_HAPTICS_WAVEFORM_RUMBLE; + iface->hid_haptics.features.waveform_list[1] = HID_USAGE_HAPTICS_WAVEFORM_BUZZ; + iface->hid_haptics.features.duration_list[0] = 0; + iface->hid_haptics.features.duration_list[1] = 0; + iface->hid_haptics.features.waveform_cutoff_time_ms = 1000; + + if (!hid_report_descriptor_append(desc, vendor_template, sizeof(vendor_template))) + return FALSE; + + return hid_report_descriptor_append(desc, haptics_template, sizeof(haptics_template)); } #include "pop_hid_macros.h" @@ -386,6 +465,29 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC io->Information = packet->reportBufferLen; io->Status = iface->hid_vtbl->haptics_start(iface, -1, left, right); } + else if (packet->reportId == haptics->waveform_report) + { + struct hid_haptics_waveform *waveform = (struct hid_haptics_waveform *)(packet->reportBuffer + 1); + struct hid_haptics_waveform *rumble = haptics->waveforms + HAPTICS_WAVEFORM_RUMBLE_INDEX; + struct hid_haptics_waveform *buzz = haptics->waveforms + HAPTICS_WAVEFORM_BUZZ_INDEX; + ULONG duration_ms; + + io->Information = sizeof(*waveform) + 1; + assert(packet->reportBufferLen == io->Information); + + if (waveform->manual_trigger == 0 || waveform->manual_trigger > HAPTICS_WAVEFORM_LAST_INDEX) + io->Status = STATUS_INVALID_PARAMETER; + else + { + if (waveform->manual_trigger == HAPTICS_WAVEFORM_STOP_INDEX) + memset(haptics->waveforms, 0, sizeof(haptics->waveforms)); + else + haptics->waveforms[waveform->manual_trigger] = *waveform; + + duration_ms = haptics->features.waveform_cutoff_time_ms; + io->Status = iface->hid_vtbl->haptics_start(iface, duration_ms, rumble->intensity, buzz->intensity); + } + } else { io->Information = 0; @@ -395,14 +497,44 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC static void hid_device_get_feature_report(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) { - io->Information = 0; - io->Status = STATUS_NOT_IMPLEMENTED; + struct hid_haptics *haptics = &iface->hid_haptics; + + if (packet->reportId == haptics->features_report) + { + struct hid_haptics_features *features = (struct hid_haptics_features *)(packet->reportBuffer + 1); + + io->Information = sizeof(*features) + 1; + assert(packet->reportBufferLen == io->Information); + + *features = haptics->features; + io->Status = STATUS_SUCCESS; + } + else + { + io->Information = 0; + io->Status = STATUS_NOT_IMPLEMENTED; + } } static void hid_device_set_feature_report(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) { - io->Information = 0; - io->Status = STATUS_NOT_IMPLEMENTED; + struct hid_haptics *haptics = &iface->hid_haptics; + + if (packet->reportId == haptics->features_report) + { + struct hid_haptics_features *features = (struct hid_haptics_features *)(packet->reportBuffer + 1); + + io->Information = sizeof(*features) + 1; + assert(packet->reportBufferLen == io->Information); + + haptics->features.waveform_cutoff_time_ms = features->waveform_cutoff_time_ms; + io->Status = STATUS_SUCCESS; + } + else + { + io->Information = 0; + io->Status = STATUS_NOT_IMPLEMENTED; + } } static const struct raw_device_vtbl raw_device_vtbl = diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index 9684ac47067..5da5ca58e7f 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -57,9 +57,35 @@ struct hid_report_descriptor BYTE next_report_id[3]; }; +enum haptics_waveform_index +{ + HAPTICS_WAVEFORM_STOP_INDEX = 1, + HAPTICS_WAVEFORM_NULL_INDEX = 2, + HAPTICS_WAVEFORM_RUMBLE_INDEX = 3, + HAPTICS_WAVEFORM_BUZZ_INDEX = 4, + HAPTICS_WAVEFORM_LAST_INDEX = HAPTICS_WAVEFORM_BUZZ_INDEX, +}; + +struct hid_haptics_features +{ + WORD waveform_list[HAPTICS_WAVEFORM_LAST_INDEX - HAPTICS_WAVEFORM_NULL_INDEX]; + WORD duration_list[HAPTICS_WAVEFORM_LAST_INDEX - HAPTICS_WAVEFORM_NULL_INDEX]; + DWORD waveform_cutoff_time_ms; +}; + +struct hid_haptics_waveform +{ + WORD manual_trigger; + WORD intensity; +}; + struct hid_haptics { + struct hid_haptics_features features; + struct hid_haptics_waveform waveforms[HAPTICS_WAVEFORM_LAST_INDEX + 1]; BYTE vendor_report; + BYTE features_report; + BYTE waveform_report; }; struct hid_device_state
1
0
0
0
Rémi Bernon : winebus.sys: Remove unused SDL_memset function pointer.
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: ef36885b1ead2c19e8f5f4b784131cbab9e7454f URL:
https://source.winehq.org/git/wine.git/?a=commit;h=ef36885b1ead2c19e8f5f4b7…
Author: Rémi Bernon <rbernon(a)codeweavers.com> Date: Fri Sep 24 11:51:53 2021 +0200 winebus.sys: Remove unused SDL_memset function pointer. Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winebus.sys/bus_sdl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index f71da77b77e..17032e1dba9 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -102,7 +102,6 @@ MAKE_FUNCPTR(SDL_HapticRumbleSupported); MAKE_FUNCPTR(SDL_HapticRunEffect); MAKE_FUNCPTR(SDL_HapticStopAll); MAKE_FUNCPTR(SDL_JoystickIsHaptic); -MAKE_FUNCPTR(SDL_memset); MAKE_FUNCPTR(SDL_GameControllerAddMapping); MAKE_FUNCPTR(SDL_RegisterEvents); MAKE_FUNCPTR(SDL_PushEvent); @@ -658,7 +657,6 @@ NTSTATUS sdl_bus_init(void *args) LOAD_FUNCPTR(SDL_HapticRunEffect); LOAD_FUNCPTR(SDL_HapticStopAll); LOAD_FUNCPTR(SDL_JoystickIsHaptic); - LOAD_FUNCPTR(SDL_memset); LOAD_FUNCPTR(SDL_GameControllerAddMapping); LOAD_FUNCPTR(SDL_RegisterEvents); LOAD_FUNCPTR(SDL_PushEvent);
1
0
0
0
Rémi Bernon : winebus.sys: Check for SDL_JoystickRumble presence at runtime.
by Alexandre Julliard
24 Sep '21
24 Sep '21
Module: wine Branch: master Commit: c3ee32e846564850bfd4c120755e9942773dd795 URL:
https://source.winehq.org/git/wine.git/?a=commit;h=c3ee32e846564850bfd4c120…
Author: Rémi Bernon <rbernon(a)codeweavers.com> Date: Fri Sep 24 11:51:52 2021 +0200 winebus.sys: Check for SDL_JoystickRumble presence at runtime. It's been introduced in SDL2 2.0.9, released on 2018/10/31. Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/winebus.sys/bus_sdl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 31915a9fa0d..f71da77b77e 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -102,11 +102,11 @@ MAKE_FUNCPTR(SDL_HapticRumbleSupported); MAKE_FUNCPTR(SDL_HapticRunEffect); MAKE_FUNCPTR(SDL_HapticStopAll); MAKE_FUNCPTR(SDL_JoystickIsHaptic); -MAKE_FUNCPTR(SDL_JoystickRumble); MAKE_FUNCPTR(SDL_memset); MAKE_FUNCPTR(SDL_GameControllerAddMapping); MAKE_FUNCPTR(SDL_RegisterEvents); MAKE_FUNCPTR(SDL_PushEvent); +static int (*pSDL_JoystickRumble)(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); static Uint16 (*pSDL_JoystickGetProduct)(SDL_Joystick * joystick); static Uint16 (*pSDL_JoystickGetProductVersion)(SDL_Joystick * joystick); static Uint16 (*pSDL_JoystickGetVendor)(SDL_Joystick * joystick); @@ -181,7 +181,7 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl) pSDL_HapticRumbleInit(impl->sdl_haptic); } - if (!pSDL_JoystickRumble(impl->sdl_joystick, 0, 0, 0)) + if (pSDL_JoystickRumble && !pSDL_JoystickRumble(impl->sdl_joystick, 0, 0, 0)) impl->effect_support |= WINE_SDL_JOYSTICK_RUMBLE; if (impl->effect_support & EFFECT_SUPPORT_HAPTICS) @@ -658,12 +658,12 @@ NTSTATUS sdl_bus_init(void *args) LOAD_FUNCPTR(SDL_HapticRunEffect); LOAD_FUNCPTR(SDL_HapticStopAll); LOAD_FUNCPTR(SDL_JoystickIsHaptic); - LOAD_FUNCPTR(SDL_JoystickRumble); LOAD_FUNCPTR(SDL_memset); LOAD_FUNCPTR(SDL_GameControllerAddMapping); LOAD_FUNCPTR(SDL_RegisterEvents); LOAD_FUNCPTR(SDL_PushEvent); #undef LOAD_FUNCPTR + pSDL_JoystickRumble = dlsym(sdl_handle, "SDL_JoystickRumble"); pSDL_JoystickGetProduct = dlsym(sdl_handle, "SDL_JoystickGetProduct"); pSDL_JoystickGetProductVersion = dlsym(sdl_handle, "SDL_JoystickGetProductVersion"); pSDL_JoystickGetVendor = dlsym(sdl_handle, "SDL_JoystickGetVendor");
1
0
0
0
← Newer
1
...
19
20
21
22
23
24
25
...
103
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
Results per page:
10
25
50
100
200