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>
This commit is contained in:
Gabriel Ivăncescu 2018-08-27 20:10:46 +03:00 committed by Alexandre Julliard
parent 36649d083f
commit 9c2217216c
1 changed files with 25 additions and 8 deletions

View File

@ -93,6 +93,14 @@ static inline IAutoCompleteImpl *impl_from_IAutoCompleteDropDown(IAutoCompleteDr
return CONTAINING_RECORD(iface, IAutoCompleteImpl, IAutoCompleteDropDown_iface); 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 Window procedure for autocompletion
*/ */
@ -276,10 +284,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
RemovePropW(hwnd, autocomplete_propertyW); RemovePropW(hwnd, autocomplete_propertyW);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)proc); SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)proc);
This->hwndEdit = NULL; destroy_autocomplete_object(This);
if (This->hwndListBox)
DestroyWindow(This->hwndListBox);
IAutoComplete2_Release(&This->IAutoComplete2_iface);
return CallWindowProcW(proc, hwnd, uMsg, wParam, lParam); return CallWindowProcW(proc, hwnd, uMsg, wParam, lParam);
} }
default: default:
@ -434,7 +439,7 @@ static HRESULT WINAPI IAutoComplete2_fnInit(
LPCOLESTR pwzsRegKeyPath, LPCOLESTR pwzsRegKeyPath,
LPCOLESTR pwszQuickComplete) LPCOLESTR pwszQuickComplete)
{ {
IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); IAutoCompleteImpl *prev, *This = impl_from_IAutoComplete2(iface);
TRACE("(%p)->(%p, %p, %s, %s)\n", TRACE("(%p)->(%p, %p, %s, %s)\n",
This, hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete)); This, hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete));
@ -461,11 +466,23 @@ static HRESULT WINAPI IAutoComplete2_fnInit(
This->initialized = TRUE; This->initialized = TRUE;
This->hwndEdit = hwndEdit; 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,
IAutoComplete2_AddRef(&This->IAutoComplete2_iface); 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); 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);
if (This->options & ACO_AUTOSUGGEST) if (This->options & ACO_AUTOSUGGEST)
create_listbox(This); create_listbox(This);