Module: wine Branch: stable Commit: ca9c9809f1dd93b7fbc393f367842532cf1b35b9 URL: https://source.winehq.org/git/wine.git/?a=commit;h=ca9c9809f1dd93b7fbc393f36...
Author: Gabriel Ivăncescu gabrielopcode@gmail.com Date: Mon Aug 27 20:10:46 2018 +0300
shell32/autocomplete: Don't crash when there's another AutoComplete object on the same edit control.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22333 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org (cherry picked from commit 9c2217216cbf9a56a5090c848119d84fac9b65ec) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
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 1a02c83..d804e42 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 */ @@ -277,10 +285,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: @@ -435,7 +440,7 @@ static HRESULT WINAPI IAutoComplete2_fnInit( LPCOLESTR pwzsRegKeyPath, LPCOLESTR pwszQuickComplete) { - IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); + IAutoCompleteImpl *prev, *This = impl_from_IAutoComplete2(iface);
TRACE("(%p)->(%p, %p, %s, %s)\n", This, hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete)); @@ -462,10 +467,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 */ + prev = GetPropW(hwndEdit, autocomplete_propertyW); + SetPropW(hwndEdit, autocomplete_propertyW, This); + + if (prev && prev->initialized) { + This->wpOrigEditProc = prev->wpOrigEditProc; + destroy_autocomplete_object(prev); + } + 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);