Commit 4dc30448 authored by Andrew Nguyen's avatar Andrew Nguyen Committed by Alexandre Julliard

shell32: Improve initialization state and parameter handling in IAutoComplete::Init.

parent 13b83456
......@@ -67,7 +67,8 @@ typedef struct
const IAutoComplete2Vtbl *lpVtbl;
const IAutoCompleteDropDownVtbl *lpDropDownVtbl;
LONG ref;
BOOL enabled;
BOOL initialized;
BOOL enabled;
HWND hwndEdit;
HWND hwndListBox;
WNDPROC wpOrigEditProc;
......@@ -246,21 +247,31 @@ static HRESULT WINAPI IAutoComplete2_fnInit(
{
IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface;
TRACE("(%p)->(0x%08lx, %p, %s, %s)\n",
This, (long)hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete));
TRACE("(%p)->(%p, %p, %s, %s)\n",
This, hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete));
if (This->options & ACO_SEARCH) FIXME(" ACO_SEARCH not supported\n");
if (This->options & ACO_FILTERPREFIXES) FIXME(" ACO_FILTERPREFIXES not supported\n");
if (This->options & ACO_USETAB) FIXME(" ACO_USETAB not supported\n");
if (This->options & ACO_RTLREADING) FIXME(" ACO_RTLREADING not supported\n");
This->hwndEdit = hwndEdit;
if (!hwndEdit || !punkACL)
return E_INVALIDARG;
if (This->initialized)
{
WARN("Autocompletion object is already initialized\n");
/* This->hwndEdit is set to NULL when the edit window is destroyed. */
return This->hwndEdit ? E_FAIL : E_UNEXPECTED;
}
if (FAILED (IUnknown_QueryInterface (punkACL, &IID_IEnumString, (LPVOID*)&This->enumstr))) {
TRACE("No IEnumString interface\n");
return E_NOINTERFACE;
WARN("No IEnumString interface\n");
return E_NOINTERFACE;
}
This->initialized = TRUE;
This->hwndEdit = hwndEdit;
This->wpOrigEditProc = (WNDPROC) SetWindowLongPtrW( hwndEdit, GWLP_WNDPROC, (LONG_PTR) ACEditSubclassProc);
SetWindowLongPtrW( hwndEdit, GWLP_USERDATA, (LONG_PTR)This);
......@@ -613,7 +624,14 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
}
}
break;
break;
case WM_DESTROY:
{
WNDPROC proc = This->wpOrigEditProc;
This->hwndEdit = NULL;
return CallWindowProcW(proc, hwnd, uMsg, wParam, lParam);
}
default:
return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
......
......@@ -33,10 +33,113 @@ static HWND hMainWnd, hEdit;
static HINSTANCE hinst;
static int killfocus_count;
static void test_invalid_init(void)
{
HRESULT hr;
IAutoComplete *ac;
IUnknown *acSource;
HWND edit_control;
/* AutoComplete instance */
hr = CoCreateInstance(&CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER,
&IID_IAutoComplete, (void **)&ac);
if (hr == REGDB_E_CLASSNOTREG)
{
win_skip("CLSID_AutoComplete is not registered\n");
return;
}
ok(hr == S_OK, "no IID_IAutoComplete (0x%08x)\n", hr);
/* AutoComplete source */
hr = CoCreateInstance(&CLSID_ACLMulti, NULL, CLSCTX_INPROC_SERVER,
&IID_IACList, (void **)&acSource);
if (hr == REGDB_E_CLASSNOTREG)
{
win_skip("CLSID_ACLMulti is not registered\n");
IAutoComplete_Release(ac);
return;
}
ok(hr == S_OK, "no IID_IACList (0x%08x)\n", hr);
edit_control = CreateWindowExA(0, "EDIT", "Some text", 0, 10, 10, 300, 300,
hMainWnd, NULL, hinst, NULL);
ok(edit_control != NULL, "Can't create edit control\n");
/* The refcount of acSource would be incremented on older Windows. */
hr = IAutoComplete_Init(ac, NULL, acSource, NULL, NULL);
ok(hr == E_INVALIDARG ||
broken(hr == S_OK), /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
if (hr == E_INVALIDARG)
{
LONG ref;
IUnknown_AddRef(acSource);
ref = IUnknown_Release(acSource);
ok(ref == 1, "Expected AutoComplete source refcount to be 1, got %d\n", ref);
}
if (0)
{
/* Older Windows versions never check the window handle, while newer
* versions only check for NULL. Subsequent attempts to initialize the
* object after this call succeeds would fail, because initialization
* state is determined by whether a non-NULL window handle is stored. */
hr = IAutoComplete_Init(ac, (HWND)0xdeadbeef, acSource, NULL, NULL);
ok(hr == S_OK, "Init returned 0x%08x\n", hr);
/* Tests crash on older Windows. */
hr = IAutoComplete_Init(ac, NULL, NULL, NULL, NULL);
ok(hr == E_INVALIDARG, "Init returned 0x%08x\n", hr);
hr = IAutoComplete_Init(ac, edit_control, NULL, NULL, NULL);
ok(hr == E_INVALIDARG, "Init returned 0x%08x\n", hr);
}
/* bind to edit control */
hr = IAutoComplete_Init(ac, edit_control, acSource, NULL, NULL);
ok(hr == S_OK, "Init returned 0x%08x\n", hr);
/* try invalid parameters after successful initialization .*/
hr = IAutoComplete_Init(ac, NULL, NULL, NULL, NULL);
ok(hr == E_INVALIDARG ||
hr == E_FAIL, /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
hr = IAutoComplete_Init(ac, NULL, acSource, NULL, NULL);
ok(hr == E_INVALIDARG ||
hr == E_FAIL, /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
hr = IAutoComplete_Init(ac, edit_control, NULL, NULL, NULL);
ok(hr == E_INVALIDARG ||
hr == E_FAIL, /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
/* try initializing twice on the same control */
hr = IAutoComplete_Init(ac, edit_control, acSource, NULL, NULL);
ok(hr == E_FAIL, "Init returned 0x%08x\n", hr);
/* try initializing with a different control */
hr = IAutoComplete_Init(ac, hEdit, acSource, NULL, NULL);
ok(hr == E_FAIL, "Init returned 0x%08x\n", hr);
DestroyWindow(edit_control);
/* try initializing with a different control after
* destroying the original initialization control */
hr = IAutoComplete_Init(ac, hEdit, acSource, NULL, NULL);
ok(hr == E_UNEXPECTED ||
hr == E_FAIL, /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
IUnknown_Release(acSource);
IAutoComplete_Release(ac);
}
static IAutoComplete *test_init(void)
{
HRESULT r;
IAutoComplete* ac;
IAutoComplete *ac;
IUnknown *acSource;
/* AutoComplete instance */
......@@ -60,14 +163,9 @@ static IAutoComplete *test_init(void)
}
ok(r == S_OK, "no IID_IACList (0x%08x)\n", r);
if (0)
{
/* crashes on native */
r = IAutoComplete_Init(ac, hEdit, NULL, NULL, NULL);
}
/* bind to edit control */
r = IAutoComplete_Init(ac, hEdit, acSource, NULL, NULL);
ok(r == S_OK, "Init failed (0x%08x)\n", r);
ok(r == S_OK, "Init returned 0x%08x\n", r);
IUnknown_Release(acSource);
......@@ -135,6 +233,7 @@ START_TEST(autocomplete)
ok(hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n");
if (!hMainWnd) return;
test_invalid_init();
ac = test_init();
if (!ac)
goto cleanup;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment