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);
}
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 *prev, *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 */
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);