[PATCH 1/3] shell32/autocomplete: Don't crash when there's another AutoComplete object on the same edit control
Gabriel Ivăncescu
gabrielopcode at gmail.com
Mon Aug 27 12:10:46 CDT 2018
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22333
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/shell32/autocomplete.c | 33 +++++++++++++++++++++++++--------
1 file changed, 25 insertions(+), 8 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index 99ce23d..5fe48e9 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -93,6 +93,14 @@ static inline IAutoCompleteImpl *impl_from_IAutoCompleteDropDown(IAutoCompleteDr
return CONTAINING_RECORD(iface, IAutoCompleteImpl, IAutoCompleteDropDown_iface);
}
+static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
+{
+ ac->hwndEdit = NULL;
+ if (ac->hwndListBox)
+ DestroyWindow(ac->hwndListBox);
+ IAutoComplete2_Release(&ac->IAutoComplete2_iface);
+}
+
/*
Window procedure for autocompletion
*/
@@ -276,10 +284,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
RemovePropW(hwnd, autocomplete_propertyW);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)proc);
- This->hwndEdit = NULL;
- if (This->hwndListBox)
- DestroyWindow(This->hwndListBox);
- IAutoComplete2_Release(&This->IAutoComplete2_iface);
+ destroy_autocomplete_object(This);
return CallWindowProcW(proc, hwnd, uMsg, wParam, lParam);
}
default:
@@ -434,7 +439,7 @@ static HRESULT WINAPI IAutoComplete2_fnInit(
LPCOLESTR pwzsRegKeyPath,
LPCOLESTR pwszQuickComplete)
{
- IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface);
+ IAutoCompleteImpl *Other, *This = impl_from_IAutoComplete2(iface);
TRACE("(%p)->(%p, %p, %s, %s)\n",
This, hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete));
@@ -461,10 +466,22 @@ static HRESULT WINAPI IAutoComplete2_fnInit(
This->initialized = TRUE;
This->hwndEdit = hwndEdit;
- This->wpOrigEditProc = (WNDPROC) SetWindowLongPtrW( hwndEdit, GWLP_WNDPROC, (LONG_PTR) ACEditSubclassProc);
- /* Keep at least one reference to the object until the edit window is destroyed. */
+
+ /* If another AutoComplete object was previously assigned to this edit control,
+ release it but keep the same callback on the control, to avoid an infinite
+ recursive loop in ACEditSubclassProc while the property is set to this object */
+ Other = GetPropW(hwndEdit, autocomplete_propertyW);
+ SetPropW(hwndEdit, autocomplete_propertyW, This);
+
+ if (Other && Other->initialized) {
+ This->wpOrigEditProc = Other->wpOrigEditProc;
+ destroy_autocomplete_object(Other);
+ }
+ else
+ This->wpOrigEditProc = (WNDPROC) SetWindowLongPtrW(hwndEdit, GWLP_WNDPROC, (LONG_PTR) ACEditSubclassProc);
+
+ /* Keep at least one reference to the object until the edit window is destroyed */
IAutoComplete2_AddRef(&This->IAutoComplete2_iface);
- SetPropW( hwndEdit, autocomplete_propertyW, This );
if (This->options & ACO_AUTOSUGGEST)
create_listbox(This);
--
1.9.1
More information about the wine-devel
mailing list