=?UTF-8?Q?Gabriel=20Iv=C4=83ncescu=20?=: shell32/autocomplete: Don' t crash when there's another AutoComplete object on the same edit control.

Alexandre Julliard julliard at winehq.org
Thu Aug 30 16:34:42 CDT 2018


Module: wine
Branch: master
Commit: 9c2217216cbf9a56a5090c848119d84fac9b65ec
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=9c2217216cbf9a56a5090c848119d84fac9b65ec

Author: Gabriel Ivăncescu <gabrielopcode at 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 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at 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 99ce23d..cf8da50 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 *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);




More information about the wine-cvs mailing list