shell32: Improve initialization state and parameter handling in IAutoComplete::Init.
This commit is contained in:
parent
13b834561b
commit
4dc304489f
|
@ -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 (FAILED (IUnknown_QueryInterface (punkACL, &IID_IEnumString, (LPVOID*)&This->enumstr))) {
|
||||
TRACE("No IEnumString interface\n");
|
||||
return E_NOINTERFACE;
|
||||
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))) {
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue