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
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
February 2023
----- 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
1 participants
599 discussions
Start a n
N
ew thread
Alex Henrie : include: Annotate CommandLineToArgvW with __WINE_DEALLOC.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: 8f2df17e84129af2942ebcfffa7d4e9b2e148fe7 URL:
https://gitlab.winehq.org/wine/wine/-/commit/8f2df17e84129af2942ebcfffa7d4e…
Author: Alex Henrie <alexhenrie24(a)gmail.com> Date: Tue Feb 21 22:29:46 2023 -0700 include: Annotate CommandLineToArgvW with __WINE_DEALLOC. --- include/shellapi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/shellapi.h b/include/shellapi.h index a00e1037bd8..ff36803fa19 100644 --- a/include/shellapi.h +++ b/include/shellapi.h @@ -671,7 +671,7 @@ typedef struct _SHSTOCKICONINFO #define SHGSI_SHELLICONSIZE SHGFI_SHELLICONSIZE WINSHELLAPI HRESULT WINAPI SHGetStockIconInfo(SHSTOCKICONID, UINT, SHSTOCKICONINFO*); -WINSHELLAPI LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR,int*); +WINSHELLAPI WCHAR** WINAPI CommandLineToArgvW(const WCHAR*,int*) __WINE_DEALLOC(LocalFree); WINSHELLAPI HICON WINAPI ExtractIconA(HINSTANCE,LPCSTR,UINT); WINSHELLAPI HICON WINAPI ExtractIconW(HINSTANCE,LPCWSTR,UINT); #define ExtractIcon WINELIB_NAME_AW(ExtractIcon)
1
0
0
0
Mohamad Al-Jaf : include: Fix BluetoothRegisterForAuthentication prototype.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: 079ff28fcecc734204b7e34352211a4ed0e0d839 URL:
https://gitlab.winehq.org/wine/wine/-/commit/079ff28fcecc734204b7e34352211a…
Author: Mohamad Al-Jaf <mohamadaljaf(a)gmail.com> Date: Tue Feb 21 18:36:07 2023 -0500 include: Fix BluetoothRegisterForAuthentication prototype. The first parameter is defined as const BLUETOOTH_DEVICE_INFO in MSDN and bluetoothapis.h. --- include/bluetoothapis.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bluetoothapis.h b/include/bluetoothapis.h index 1942513fab3..d3b5c941b7c 100644 --- a/include/bluetoothapis.h +++ b/include/bluetoothapis.h @@ -225,7 +225,7 @@ DWORD WINAPI BluetoothGetDeviceInfo(HANDLE, BLUETOOTH_DEVICE_INFO *); DWORD WINAPI BluetoothGetRadioInfo(HANDLE, PBLUETOOTH_RADIO_INFO); BOOL WINAPI BluetoothIsConnectable(HANDLE); BOOL WINAPI BluetoothIsDiscoverable(HANDLE); -DWORD WINAPI BluetoothRegisterForAuthentication(BLUETOOTH_DEVICE_INFO *, HBLUETOOTH_AUTHENTICATION_REGISTRATION *, PFN_AUTHENTICATION_CALLBACK, void *); +DWORD WINAPI BluetoothRegisterForAuthentication(const BLUETOOTH_DEVICE_INFO *, HBLUETOOTH_AUTHENTICATION_REGISTRATION *, PFN_AUTHENTICATION_CALLBACK, void *); DWORD WINAPI BluetoothRegisterForAuthenticationEx(const BLUETOOTH_DEVICE_INFO *, HBLUETOOTH_AUTHENTICATION_REGISTRATION *, PFN_AUTHENTICATION_CALLBACK_EX, void *); DWORD WINAPI BluetoothRemoveDevice(BLUETOOTH_ADDRESS *); #define BluetoothEnumAttributes BluetoothSdpEnumAttributes
1
0
0
0
Connor McAdams : uiautomationcore: Implement IUIAutomationElement::get_CurrentBoundingRectangle.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: ba960ed49954dc5c4a48bf71780a02c83dff8c68 URL:
https://gitlab.winehq.org/wine/wine/-/commit/ba960ed49954dc5c4a48bf71780a02…
Author: Connor McAdams <cmcadams(a)codeweavers.com> Date: Fri Feb 3 12:37:41 2023 -0500 uiautomationcore: Implement IUIAutomationElement::get_CurrentBoundingRectangle. Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com> --- dlls/uiautomationcore/tests/uiautomation.c | 105 ++++++++++++++++++++++++++++- dlls/uiautomationcore/uia_com_client.c | 27 +++++++- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 1fd25a49441..73b0db3073c 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -4968,6 +4968,34 @@ static const struct prov_method_sequence get_bounding_rect_seq[] = { { 0 } }; +static const struct prov_method_sequence get_bounding_rect_seq2[] = { + { &Provider, PROV_GET_PROPERTY_VALUE }, + NODE_CREATE_SEQ(&Provider_child), + { &Provider_child, FRAG_GET_BOUNDING_RECT }, + /* + * Win10v21H2+ and above call these, attempting to get the fragment root's + * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling. + */ + { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, + { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, + { 0 } +}; + +static const struct prov_method_sequence get_bounding_rect_seq3[] = { + { &Provider_child, FRAG_GET_BOUNDING_RECT }, + /* + * Win10v21H2+ and above call these, attempting to get the fragment root's + * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling. + */ + { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, + { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, + { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ + { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, + { 0 } +}; + static const struct prov_method_sequence get_empty_bounding_rect_seq[] = { { &Provider_child, FRAG_GET_BOUNDING_RECT }, { 0 } @@ -5028,6 +5056,18 @@ static void check_uia_rect_val_(VARIANT *v, struct UiaRect *rect, const char *fi ok_(file, line)(tmp[3] == rect->height, "Unexpected height value %f, expected %f\n", tmp[3], rect->height); } +#define check_uia_rect_rect_val( rect, uia_rect ) \ + check_uia_rect_rect_val_( (rect), (uia_rect), __FILE__, __LINE__) +static void check_uia_rect_rect_val_(RECT *rect, struct UiaRect *uia_rect, const char *file, int line) +{ + ok_(file, line)(rect->left == (LONG)uia_rect->left, "Unexpected left value %ld, expected %ld\n", rect->left, (LONG)uia_rect->left); + ok_(file, line)(rect->top == (LONG)uia_rect->top, "Unexpected top value %ld, expected %ld\n", rect->top, (LONG)uia_rect->top); + ok_(file, line)(rect->right == (LONG)(uia_rect->left + uia_rect->width), "Unexpected right value %ld, expected %ld\n", rect->right, + (LONG)(uia_rect->left + uia_rect->width)); + ok_(file, line)(rect->bottom == (LONG)(uia_rect->top + uia_rect->height), "Unexpected bottom value %ld, expected %ld\n", rect->bottom, + (LONG)(uia_rect->top + uia_rect->height)); +} + static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com) { LONG idx; @@ -9793,11 +9833,13 @@ static void test_Element_GetPropertyValue(IUIAutomation *uia_iface) HWND hwnd = create_test_hwnd("test_Element_GetPropertyValue class"); const struct uia_element_property *elem_prop; struct Provider_prop_override prop_override; - IUIAutomationElement *element; + IUIAutomationElement *element, *element2; int i, prop_id, tmp_int; + struct UiaRect uia_rect; IUnknown *unk_ns; BSTR tmp_bstr; HRESULT hr; + RECT rect; VARIANT v; element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE); @@ -9902,9 +9944,68 @@ static void test_Element_GetPropertyValue(IUIAutomation *uia_iface) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); SysFreeString(tmp_bstr); - Provider.ret_invalid_prop_type = FALSE; + initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE); ok_method_sequence(get_prop_invalid_type_seq, NULL); + /* + * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND. + * It's the only version with this behavior. + */ + if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID)) + { + win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n"); + goto exit; + } + + /* + * IUIAutomationElement_get_CurrentBoundingRectangle/UIA_BoundRectanglePropertyId tests. + */ + hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v)); + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref); + + hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!element2, "element2 == NULL\n"); + VariantClear(&v); + + /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */ + set_uia_rect(&uia_rect, 0, 0, 50, 50); + Provider_child.bounds_rect = uia_rect; + hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_uia_rect_val(&v, &uia_rect); + VariantClear(&v); + ok_method_sequence(get_bounding_rect_seq2, "get_bounding_rect_seq2"); + + hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_uia_rect_rect_val(&rect, &uia_rect); + memset(&rect, 0, sizeof(rect)); + ok_method_sequence(get_bounding_rect_seq3, "get_bounding_rect_seq3"); + + /* Empty bounding rectangle will return ReservedNotSupportedValue. */ + set_uia_rect(&uia_rect, 0, 0, 0, 0); + Provider_child.bounds_rect = uia_rect; + hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v)); + ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v)); + VariantClear(&v); + ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq"); + + /* Returns an all 0 rect. */ + hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_uia_rect_rect_val(&rect, &uia_rect); + ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq"); + + IUIAutomationElement_Release(element2); + ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref); + initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE); + +exit: IUIAutomationElement_Release(element); ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index 8cc39a9342f..b6f308275bb 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -402,8 +402,31 @@ static HRESULT WINAPI uia_element_get_CurrentItemStatus(IUIAutomationElement9 *i static HRESULT WINAPI uia_element_get_CurrentBoundingRectangle(IUIAutomationElement9 *iface, RECT *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + HRESULT hr; + VARIANT v; + + TRACE("%p, %p\n", element, ret_val); + + memset(ret_val, 0, sizeof(*ret_val)); + VariantInit(&v); + hr = UiaGetPropertyValue(element->node, UIA_BoundingRectanglePropertyId, &v); + if (SUCCEEDED(hr) && V_VT(&v) == (VT_R8 | VT_ARRAY)) + { + double vals[4]; + LONG idx; + + for (idx = 0; idx < ARRAY_SIZE(vals); idx++) + SafeArrayGetElement(V_ARRAY(&v), &idx, &vals[idx]); + + ret_val->left = vals[0]; + ret_val->top = vals[1]; + ret_val->right = ret_val->left + vals[2]; + ret_val->bottom = ret_val->top + vals[3]; + } + + VariantClear(&v); + return hr; } static HRESULT WINAPI uia_element_get_CurrentLabeledBy(IUIAutomationElement9 *iface, IUIAutomationElement **ret_val)
1
0
0
0
Connor McAdams : uiautomationcore: Implement IUIAutomationElement::get_CurrentName.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: c31e5313184380e1ec31a06ee62d2c9ae971b215 URL:
https://gitlab.winehq.org/wine/wine/-/commit/c31e5313184380e1ec31a06ee62d2c…
Author: Connor McAdams <cmcadams(a)codeweavers.com> Date: Fri Feb 3 09:36:10 2023 -0500 uiautomationcore: Implement IUIAutomationElement::get_CurrentName. Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com> --- dlls/uiautomationcore/tests/uiautomation.c | 20 ++++++++++++++++++++ dlls/uiautomationcore/uia_com_client.c | 17 +++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index a5b15726c21..1fd25a49441 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -9796,6 +9796,7 @@ static void test_Element_GetPropertyValue(IUIAutomation *uia_iface) IUIAutomationElement *element; int i, prop_id, tmp_int; IUnknown *unk_ns; + BSTR tmp_bstr; HRESULT hr; VARIANT v; @@ -9885,6 +9886,25 @@ static void test_Element_GetPropertyValue(IUIAutomation *uia_iface) set_provider_prop_override(&Provider, NULL, 0); ok_method_sequence(get_prop_seq, NULL); + /* + * IUIAutomationElement_get_CurrentName tests. + */ + tmp_bstr = NULL; + hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); + SysFreeString(tmp_bstr); + ok_method_sequence(get_prop_seq, NULL); + + tmp_bstr = NULL; + Provider.ret_invalid_prop_type = TRUE; + hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); + SysFreeString(tmp_bstr); + Provider.ret_invalid_prop_type = FALSE; + ok_method_sequence(get_prop_invalid_type_seq, NULL); + IUIAutomationElement_Release(element); ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index dad5938a760..8cc39a9342f 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -269,8 +269,21 @@ static HRESULT WINAPI uia_element_get_CurrentLocalizedControlType(IUIAutomationE static HRESULT WINAPI uia_element_get_CurrentName(IUIAutomationElement9 *iface, BSTR *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + HRESULT hr; + VARIANT v; + + TRACE("%p, %p\n", iface, ret_val); + + VariantInit(&v); + hr = UiaGetPropertyValue(element->node, UIA_NamePropertyId, &v); + if (SUCCEEDED(hr) && V_VT(&v) == VT_BSTR && V_BSTR(&v)) + *ret_val = SysAllocString(V_BSTR(&v)); + else + *ret_val = SysAllocString(L""); + + VariantClear(&v); + return hr; } static HRESULT WINAPI uia_element_get_CurrentAcceleratorKey(IUIAutomationElement9 *iface, BSTR *ret_val)
1
0
0
0
Connor McAdams : uiautomationcore: Implement IUIAutomationElement::get_CurrentControlType.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: 0b487338f373b41aeeaed76a531262db9f4b1b72 URL:
https://gitlab.winehq.org/wine/wine/-/commit/0b487338f373b41aeeaed76a531262…
Author: Connor McAdams <cmcadams(a)codeweavers.com> Date: Thu Feb 2 16:37:43 2023 -0500 uiautomationcore: Implement IUIAutomationElement::get_CurrentControlType. Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com> --- dlls/uiautomationcore/tests/uiautomation.c | 38 +++++++++++++++++++++++++++++- dlls/uiautomationcore/uia_com_client.c | 22 +++++++++++++++-- dlls/uiautomationcore/uia_ids.c | 20 ++++++++++++++++ dlls/uiautomationcore/uia_private.h | 1 + 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index a5f609511ed..a5b15726c21 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -9792,9 +9792,10 @@ static void test_Element_GetPropertyValue(IUIAutomation *uia_iface) { HWND hwnd = create_test_hwnd("test_Element_GetPropertyValue class"); const struct uia_element_property *elem_prop; + struct Provider_prop_override prop_override; IUIAutomationElement *element; + int i, prop_id, tmp_int; IUnknown *unk_ns; - int i, prop_id; HRESULT hr; VARIANT v; @@ -9849,6 +9850,41 @@ static void test_Element_GetPropertyValue(IUIAutomation *uia_iface) winetest_pop_context(); } + /* + * IUIAutomationElement_get_CurrentControlType tests. If the value + * returned for UIA_ControlTypePropertyId is not a registered control + * type ID, we'll get back UIA_CustomControlTypeId. + */ + tmp_int = 0xdeadb33f; + hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* + * Win10v1507 and below don't check whether or not the returned control + * type ID is valid. + */ + ok(tmp_int == UIA_CustomControlTypeId || broken(tmp_int == 0xdeadbeef), "Unexpected control type %#x\n", tmp_int); + ok_method_sequence(get_prop_seq, NULL); + + Provider.ret_invalid_prop_type = TRUE; + tmp_int = 0xdeadbeef; + hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int); + Provider.ret_invalid_prop_type = FALSE; + ok_method_sequence(get_prop_invalid_type_seq, NULL); + + /* Finally, a valid control type. */ + V_VT(&v) = VT_I4; + V_I4(&v) = UIA_HyperlinkControlTypeId; + set_property_override(&prop_override, UIA_ControlTypePropertyId, &v); + set_provider_prop_override(&Provider, &prop_override, 1); + hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int); + set_provider_prop_override(&Provider, NULL, 0); + ok_method_sequence(get_prop_seq, NULL); + IUIAutomationElement_Release(element); ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index 6eea03a4d32..dad5938a760 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -239,8 +239,26 @@ static HRESULT WINAPI uia_element_get_CurrentProcessId(IUIAutomationElement9 *if static HRESULT WINAPI uia_element_get_CurrentControlType(IUIAutomationElement9 *iface, CONTROLTYPEID *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + const struct uia_control_type_info *control_type_info = NULL; + HRESULT hr; + VARIANT v; + + TRACE("%p, %p\n", iface, ret_val); + + VariantInit(&v); + *ret_val = UIA_CustomControlTypeId; + hr = UiaGetPropertyValue(element->node, UIA_ControlTypePropertyId, &v); + if (SUCCEEDED(hr) && V_VT(&v) == VT_I4) + { + if ((control_type_info = uia_control_type_info_from_id(V_I4(&v)))) + *ret_val = control_type_info->control_type_id; + else + WARN("Provider returned invalid control type ID %ld\n", V_I4(&v)); + } + + VariantClear(&v); + return hr; } static HRESULT WINAPI uia_element_get_CurrentLocalizedControlType(IUIAutomationElement9 *iface, BSTR *ret_val) diff --git a/dlls/uiautomationcore/uia_ids.c b/dlls/uiautomationcore/uia_ids.c index bd49890cdc5..64f2ecced93 100644 --- a/dlls/uiautomationcore/uia_ids.c +++ b/dlls/uiautomationcore/uia_ids.c @@ -566,6 +566,18 @@ static const struct uia_control_type_info default_uia_control_types[] = { { &ListItem_Control_GUID, UIA_ListItemControlTypeId }, }; +static const int control_type_id_idx[] = { + 0x12, 0x17, 0x04, 0x13, 0x1f, 0x05, 0x27, 0x28, + 0x26, 0x09, 0x0f, 0x23, 0x16, 0x24, 0x07, 0x0d, + 0x08, 0x01, 0x06, 0x0e, 0x25, 0x10, 0x22, 0x19, + 0x1c, 0x1e, 0x02, 0x15, 0x1b, 0x0b, 0x14, 0x03, + 0x0a, 0x11, 0x21, 0x20, 0x00, 0x1d, 0x1a, 0x0c, + 0x18, +}; + +#define CONTROL_TYPE_ID_MIN 50000 +#define CONTROL_TYPE_ID_MAX (CONTROL_TYPE_ID_MIN + ARRAY_SIZE(default_uia_control_types)) + static const struct uia_control_type_info *uia_control_type_info_from_guid(const GUID *guid) { struct uia_control_type_info *control_type; @@ -577,6 +589,14 @@ static const struct uia_control_type_info *uia_control_type_info_from_guid(const return NULL; } +const struct uia_control_type_info *uia_control_type_info_from_id(CONTROLTYPEID control_type_id) +{ + if ((control_type_id < CONTROL_TYPE_ID_MIN) || (control_type_id > CONTROL_TYPE_ID_MAX)) + return NULL; + + return &default_uia_control_types[control_type_id_idx[control_type_id - CONTROL_TYPE_ID_MIN]]; +} + /*********************************************************************** * UiaLookupId (uiautomationcore.@) */ diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 814ad43d686..157ae3583f8 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -110,6 +110,7 @@ HRESULT create_uia_iface(IUnknown **iface, BOOL is_cui8) DECLSPEC_HIDDEN; /* uia_ids.c */ const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN; const struct uia_pattern_info *uia_pattern_info_from_id(PATTERNID pattern_id) DECLSPEC_HIDDEN; +const struct uia_control_type_info *uia_control_type_info_from_id(CONTROLTYPEID control_type_id) DECLSPEC_HIDDEN; /* uia_provider.c */ void uia_stop_provider_thread(void) DECLSPEC_HIDDEN;
1
0
0
0
Connor McAdams : uiautomationcore: Implement UiaLookupId for AutomationIdentifierType_ControlType GUIDs.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: 21e6fd5076d3b35fb69d7d579e5bf506d3763154 URL:
https://gitlab.winehq.org/wine/wine/-/commit/21e6fd5076d3b35fb69d7d579e5bf5…
Author: Connor McAdams <cmcadams(a)codeweavers.com> Date: Thu Feb 2 16:06:20 2023 -0500 uiautomationcore: Implement UiaLookupId for AutomationIdentifierType_ControlType GUIDs. Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com> --- dlls/uiautomationcore/tests/uiautomation.c | 46 +++++++++++++++++++ dlls/uiautomationcore/uia_classes.idl | 5 ++ dlls/uiautomationcore/uia_ids.c | 74 ++++++++++++++++++++++++++++++ include/uiautomationcoreapi.h | 45 ++++++++++++++++++ 4 files changed, 170 insertions(+)
1
0
0
0
Eric Pouech : kernel32/tests: Fix debugger.c:test_kill_on_exit().
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: 53fc157f9f2bdfb2530f9fdbfe903cc4b6eb704c URL:
https://gitlab.winehq.org/wine/wine/-/commit/53fc157f9f2bdfb2530f9fdbfe903c…
Author: Eric Pouech <eric.pouech(a)gmail.com> Date: Mon Feb 20 18:18:33 2023 +0100 kernel32/tests: Fix debugger.c:test_kill_on_exit(). As background information from Windows testings: - the debug port event is closed upon thread regular exit. - results are however inconsistent across Windows versions for forced termination (through TerminateThread and equiv). - this is moreover crippled by most of the 32bit implementation on Windows (except Win8) which don't enforce the close on exit flag for wow64 debuggee:s (they enforce it for 64bit though) - but, in the cases where the debuggee terminates, the debug port is always closed *after* the debuggee process termination. So I adapted the tests to conform to "debug port is closed" when handling the thread termination. Some tests had to be moved *after* debuggee termination to ensure success. Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=53144
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com> --- dlls/kernel32/tests/debugger.c | 47 ++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index baf8d2749c7..2491b1093f1 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -2098,6 +2098,7 @@ static void test_kill_on_exit(const char *argv0) HANDLE event, debug, thread; DWORD exit_code, tid; ULONG val; + BOOL ret; event = CreateEventW(&sa, FALSE, FALSE, NULL); ok(event != NULL, "CreateEvent failed: %lu\n", GetLastError()); @@ -2169,29 +2170,46 @@ static void test_kill_on_exit(const char *argv0) CloseHandle( pi.hThread ); CloseHandle( thread ); - /* but not on forced exit */ + /* checking on forced exit */ status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE ); ok( !status, "NtCreateDebugObject failed %lx\n", status ); thread = CreateThread(NULL, 0, debug_and_wait, &debug, 0, &tid); Sleep( 100 ); ok( debug != 0, "no debug port\n" ); - val = 1; + val = DEBUG_KILL_ON_CLOSE; status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation, &val, sizeof(val), NULL ); ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %lx\n", status ); TerminateThread( thread, 0 ); - status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation, - &val, sizeof(val), NULL ); - ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %lx\n", status ); - WaitForSingleObject( pi.hProcess, 300 ); - GetExitCodeProcess( pi.hProcess, &exit_code ); - todo_wine - ok( exit_code == STATUS_DEBUGGER_INACTIVE || broken(exit_code == STILL_ACTIVE), /* wow64 */ - "exit code = %08lx\n", exit_code); + + status = WaitForSingleObject( pi.hProcess, 1500 ); + if (status != WAIT_OBJECT_0) + { + todo_wine /* Wine doesn't handle debug port of TerminateThread */ + ok(broken(sizeof(void*) == sizeof(int)), /* happens consistently on 32bit on Win7, 10 & 11 */ + "Terminating thread should terminate debuggee\n"); + + ret = TerminateProcess( pi.hProcess, 0 ); + ok(ret, "TerminateProcess failed: %lu\n", GetLastError()); + CloseHandle( debug ); + } + else + { + ok(status == WAIT_OBJECT_0, "debuggee didn't terminate %lx\n", status); + ret = GetExitCodeProcess( pi.hProcess, &exit_code ); + ok(ret, "No exit code: %lu\n", GetLastError()); + todo_wine + ok( exit_code == STATUS_DEBUGGER_INACTIVE || broken(exit_code == STILL_ACTIVE), /* wow64 */ + "exit code = %08lx\n", exit_code); + status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation, + &val, sizeof(val), NULL ); + todo_wine + ok( status == STATUS_INVALID_HANDLE, "NtSetInformationDebugObject failed %lx\n", status ); + } + CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); CloseHandle( thread ); - CloseHandle( debug ); debug = 0; thread = CreateThread(NULL, 0, create_debug_port, &debug, 0, &tid); @@ -2202,10 +2220,13 @@ static void test_kill_on_exit(const char *argv0) &val, sizeof(val), NULL ); ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %lx\n", status ); TerminateThread( thread, 0 ); + Sleep( 200 ); status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation, &val, sizeof(val), NULL ); - ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %lx\n", status ); - CloseHandle( debug ); + todo_wine + ok( status == STATUS_INVALID_HANDLE || broken( status == STATUS_SUCCESS ), + "NtSetInformationDebugObject failed %lx\n", status ); + if (status != STATUS_INVALID_HANDLE) CloseHandle( debug ); CloseHandle( thread ); CloseHandle( event );
1
0
0
0
Eric Pouech : dbghelp/tests: Fix failure on Win10 1607.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: 3bbb2caf08efd16beb77a11297d4fa7b71071d69 URL:
https://gitlab.winehq.org/wine/wine/-/commit/3bbb2caf08efd16beb77a11297d4fa…
Author: Eric Pouech <eric.pouech(a)gmail.com> Date: Mon Feb 20 18:18:32 2023 +0100 dbghelp/tests: Fix failure on Win10 1607. Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=54534
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com> --- dlls/dbghelp/tests/dbghelp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dlls/dbghelp/tests/dbghelp.c b/dlls/dbghelp/tests/dbghelp.c index 5a1e6121931..618ee6e8cdb 100644 --- a/dlls/dbghelp/tests/dbghelp.c +++ b/dlls/dbghelp/tests/dbghelp.c @@ -537,7 +537,8 @@ static BOOL CALLBACK aggregate_cb(PCWSTR imagename, DWORD64 base, ULONG sz, PVOI { ok(!ret, "Module %ls shouldn't be loaded\n", imagename); ret = SymLoadModuleExW(aggregation->proc, NULL, imagename, NULL, base, sz, NULL, 0); - ok(ret, "SymLoadModuleExW failed on %ls: %lu\n", imagename, GetLastError()); + ok(ret || broken(GetLastError() == ERROR_SUCCESS) /* Win10/64 v1607 return this on bcryptPrimitives.DLL */, + "SymLoadModuleExW failed on %ls: %lu\n", imagename, GetLastError()); ret = SymGetModuleInfoW64(aggregation->proc, base, &im); ok(ret, "SymGetModuleInfoW64 failed: %lu\n", GetLastError()); }
1
0
0
0
Eric Pouech : kernel32/tests: Don't let debugger tests fail on a 64bit only config.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: 23b082ed1da89d4bab0a149a54aa52bd61c63c6b URL:
https://gitlab.winehq.org/wine/wine/-/commit/23b082ed1da89d4bab0a149a54aa52…
Author: Eric Pouech <eric.pouech(a)gmail.com> Date: Mon Feb 20 18:18:30 2023 +0100 kernel32/tests: Don't let debugger tests fail on a 64bit only config. Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com> --- dlls/kernel32/tests/debugger.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index 513db658222..baf8d2749c7 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -1001,6 +1001,17 @@ static void test_debug_loop(int argc, char **argv) win_skip("CheckRemoteDebuggerPresent not available, skipping test.\n"); return; } + if (sizeof(void *) > sizeof(int)) + { + WCHAR buffer[MAX_PATH]; + GetSystemWow64DirectoryW( buffer, MAX_PATH ); + wcscat( buffer, L"\\oleacc.dll" ); + if (GetFileAttributesW( buffer ) == INVALID_FILE_ATTRIBUTES) + { + skip("Skipping test on 64bit only configuration\n"); + return; + } + } pid = GetCurrentProcessId(); ret = DebugActiveProcess(pid);
1
0
0
0
Rémi Bernon : ntdll: Add a heap thread affinity and per-affinity bin group cache.
by Alexandre Julliard
22 Feb '23
22 Feb '23
Module: wine Branch: master Commit: 40b7c3e89a95d6ccb190b234d4ad13b3a8304495 URL:
https://gitlab.winehq.org/wine/wine/-/commit/40b7c3e89a95d6ccb190b234d4ad13…
Author: Rémi Bernon <rbernon(a)codeweavers.com> Date: Fri Feb 10 08:10:01 2023 +0100 ntdll: Add a heap thread affinity and per-affinity bin group cache. --- dlls/ntdll/heap.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++--- dlls/ntdll/loader.c | 2 ++ dlls/ntdll/ntdll_misc.h | 1 + 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index b2d08a1de7d..afe38eddaa8 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -255,6 +255,9 @@ C_ASSERT( BLOCK_BIN_SIZE( 0x80 ) == ~(SIZE_T)0 ); /* difference between block classes and all possible validation overhead must fit into block tail_size */ C_ASSERT( BIN_SIZE_STEP_7 + 3 * BLOCK_ALIGN <= FIELD_MAX( struct block, tail_size ) ); +static BYTE affinity_mapping[] = {20,6,31,15,14,29,27,4,18,24,26,13,0,9,2,30,17,7,23,25,10,19,12,3,22,21,5,16,1,28,11,8}; +static LONG next_thread_affinity; + /* a bin, tracking heap blocks of a certain size */ struct bin { @@ -265,8 +268,20 @@ struct bin /* list of groups with free blocks */ SLIST_HEADER groups; + + /* array of affinity reserved groups, interleaved with other bins to keep + * all pointers of the same affinity and different bin grouped together, + * and pointers of the same bin and different affinity away from each other, + * hopefully in separate cache lines. + */ + struct group **affinity_group_base; }; +static inline struct group **bin_get_affinity_group( struct bin *bin, BYTE affinity ) +{ + return bin->affinity_group_base + affinity * BLOCK_SIZE_BIN_COUNT; +} + struct heap { /* win32/win64 */ DWORD_PTR unknown1[2]; /* 0000/0000 */ @@ -1531,11 +1546,16 @@ HANDLE WINAPI RtlCreateHeap( ULONG flags, void *addr, SIZE_T total_size, SIZE_T if (heap->flags & HEAP_GROWABLE) { - SIZE_T size = sizeof(struct bin) * BLOCK_SIZE_BIN_COUNT; + SIZE_T size = (sizeof(struct bin) + sizeof(struct group *) * ARRAY_SIZE(affinity_mapping)) * BLOCK_SIZE_BIN_COUNT; NtAllocateVirtualMemory( NtCurrentProcess(), (void *)&heap->bins, 0, &size, MEM_COMMIT, PAGE_READWRITE ); - for (i = 0; i < BLOCK_SIZE_BIN_COUNT; ++i) + + for (i = 0; heap->bins && i < BLOCK_SIZE_BIN_COUNT; ++i) + { RtlInitializeSListHead( &heap->bins[i].groups ); + /* offset affinity_group_base to interleave the bin affinity group pointers */ + heap->bins[i].affinity_group_base = (struct group **)(heap->bins + BLOCK_SIZE_BIN_COUNT) + i; + } } /* link it into the per-process heap list */ @@ -1693,6 +1713,8 @@ struct DECLSPEC_ALIGN(BLOCK_ALIGN) group SLIST_ENTRY entry; /* one bit for each free block and the highest bit for GROUP_FLAG_FREE */ LONG free_bits; + /* affinity of the thread which last allocated from this group */ + LONG affinity; /* first block of a group, required for alignment */ struct block first_block; }; @@ -1792,11 +1814,30 @@ static NTSTATUS group_release( struct heap *heap, ULONG flags, struct bin *bin, return status; } +static inline ULONG heap_current_thread_affinity(void) +{ + ULONG affinity; + + if (!(affinity = NtCurrentTeb()->HeapVirtualAffinity)) + { + affinity = InterlockedIncrement( &next_thread_affinity ); + affinity = affinity_mapping[affinity % ARRAY_SIZE(affinity_mapping)]; + NtCurrentTeb()->HeapVirtualAffinity = affinity; + } + + return affinity; +} + /* acquire a group from the bin, thread takes ownership of a shared group or allocates a new one */ static struct group *heap_acquire_bin_group( struct heap *heap, ULONG flags, SIZE_T block_size, struct bin *bin ) { + ULONG affinity = NtCurrentTeb()->HeapVirtualAffinity; + struct group *group; SLIST_ENTRY *entry; + if ((group = InterlockedExchangePointer( (void *)bin_get_affinity_group( bin, affinity ), NULL ))) + return group; + if ((entry = RtlInterlockedPopEntrySList( &bin->groups ))) return CONTAINING_RECORD( entry, struct group, entry ); @@ -1806,8 +1847,16 @@ static struct group *heap_acquire_bin_group( struct heap *heap, ULONG flags, SIZ /* release a thread owned and fully freed group to the bin shared group, or free its memory */ static NTSTATUS heap_release_bin_group( struct heap *heap, ULONG flags, struct bin *bin, struct group *group ) { + ULONG affinity = group->affinity; + + /* using InterlockedExchangePointer here would possibly return a group that has used blocks, + * we prefer keeping our fully freed group instead for reduced memory consumption. + */ + if (!InterlockedCompareExchangePointer( (void *)bin_get_affinity_group( bin, affinity ), group, NULL )) + return STATUS_SUCCESS; + /* try re-using the block group instead of releasing it */ - if (!RtlQueryDepthSList( &bin->groups )) + if (RtlQueryDepthSList( &bin->groups ) <= ARRAY_SIZE(affinity_mapping)) { RtlInterlockedPushEntrySList( &bin->groups, &group->entry ); return STATUS_SUCCESS; @@ -1818,6 +1867,7 @@ static NTSTATUS heap_release_bin_group( struct heap *heap, ULONG flags, struct b static struct block *find_free_bin_block( struct heap *heap, ULONG flags, SIZE_T block_size, struct bin *bin ) { + ULONG affinity = heap_current_thread_affinity(); struct block *block; struct group *group; @@ -1825,13 +1875,16 @@ static struct block *find_free_bin_block( struct heap *heap, ULONG flags, SIZE_T * some other thread might still set the free bits if they are freeing blocks. */ if (!(group = heap_acquire_bin_group( heap, flags, block_size, bin ))) return NULL; + group->affinity = affinity; + block = group_find_free_block( group, block_size ); /* serialize with heap_free_block_lfh: atomically set GROUP_FLAG_FREE when the free bits are all 0. */ if (ReadNoFence( &group->free_bits ) || InterlockedCompareExchange( &group->free_bits, GROUP_FLAG_FREE, 0 )) { /* if GROUP_FLAG_FREE isn't set, thread is responsible for putting it back into group list. */ - RtlInterlockedPushEntrySList( &bin->groups, &group->entry ); + if ((group = InterlockedExchangePointer( (void *)bin_get_affinity_group( bin, affinity ), group ))) + RtlInterlockedPushEntrySList( &bin->groups, &group->entry ); } return block; @@ -1922,6 +1975,35 @@ static void bin_try_enable( struct heap *heap, struct bin *bin ) WriteRelease( &bin->enabled, TRUE ); } +static void heap_thread_detach_bin_groups( struct heap *heap ) +{ + ULONG i, affinity = NtCurrentTeb()->HeapVirtualAffinity; + + if (!heap->bins) return; + + for (i = 0; i < BLOCK_SIZE_BIN_COUNT; ++i) + { + struct bin *bin = heap->bins + i; + struct group *group; + if (!(group = InterlockedExchangePointer( (void *)bin_get_affinity_group( bin, affinity ), NULL ))) continue; + RtlInterlockedPushEntrySList( &bin->groups, &group->entry ); + } +} + +void heap_thread_detach(void) +{ + struct heap *heap; + + RtlEnterCriticalSection( &process_heap->cs ); + + LIST_FOR_EACH_ENTRY( heap, &process_heap->entry, struct heap, entry ) + heap_thread_detach_bin_groups( heap ); + + heap_thread_detach_bin_groups( process_heap ); + + RtlLeaveCriticalSection( &process_heap->cs ); +} + /*********************************************************************** * RtlAllocateHeap (NTDLL.@) */ diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index f254f1beefd..f533db060d0 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -3778,6 +3778,8 @@ void WINAPI LdrShutdownThread(void) /* don't call DbgUiGetThreadDebugObject as some apps hook it and terminate if called */ if (NtCurrentTeb()->DbgSsReserved[1]) NtClose( NtCurrentTeb()->DbgSsReserved[1] ); RtlFreeThreadActivationContextStack(); + + heap_thread_detach(); } diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index d1a7790991b..f6b77b79cde 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -127,5 +127,6 @@ static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len ) /* FLS data */ extern TEB_FLS_DATA *fls_alloc_data(void) DECLSPEC_HIDDEN; +extern void heap_thread_detach(void) DECLSPEC_HIDDEN; #endif
1
0
0
0
← Newer
1
...
12
13
14
15
16
17
18
...
60
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
Results per page:
10
25
50
100
200