blob: 7a0737caff514c0b3f337a98997e96ec9ee02701 [file] [log] [blame]
/*
* oleacc tests
*
* Copyright 2008 Nikolay Sivov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "wine/test.h"
#include <stdio.h>
#include "initguid.h"
#include <oleacc.h>
#define DEFINE_EXPECT(func) \
static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
#define SET_EXPECT(func) \
do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
#define CHECK_EXPECT2(func) \
do { \
ok(expect_ ##func, "unexpected call " #func "\n"); \
called_ ## func = TRUE; \
}while(0)
#define CHECK_EXPECT(func) \
do { \
CHECK_EXPECT2(func); \
expect_ ## func = FALSE; \
}while(0)
#define CHECK_CALLED(func) \
do { \
ok(called_ ## func, "expected " #func "\n"); \
expect_ ## func = called_ ## func = FALSE; \
}while(0)
DEFINE_EXPECT(Accessible_QI_IEnumVARIANT);
DEFINE_EXPECT(Accessible_get_accChildCount);
DEFINE_EXPECT(Accessible_get_accChild);
static HANDLE (WINAPI *pGetProcessHandleFromHwnd)(HWND);
static BOOL init(void)
{
HMODULE oleacc = GetModuleHandleA("oleacc.dll");
pGetProcessHandleFromHwnd = (void*)GetProcAddress(oleacc, "GetProcessHandleFromHwnd");
if(!pGetProcessHandleFromHwnd) {
win_skip("GetProcessHandleFromHwnd not available\n");
return FALSE;
}
return TRUE;
}
static HRESULT WINAPI Accessible_QueryInterface(
IAccessible *iface, REFIID riid, void **ppvObject)
{
if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
CHECK_EXPECT(Accessible_QI_IEnumVARIANT);
return E_NOINTERFACE;
}
ok(0, "unexpected QI call: %s\n", wine_dbgstr_guid(riid));
return E_NOTIMPL;
}
static ULONG WINAPI Accessible_AddRef(IAccessible *iface)
{
return 2;
}
static ULONG WINAPI Accessible_Release(IAccessible *iface)
{
return 1;
}
static HRESULT WINAPI Accessible_GetTypeInfoCount(
IAccessible *iface, UINT *pctinfo)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_GetTypeInfo(IAccessible *iface,
UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_GetIDsOfNames(IAccessible *iface, REFIID riid,
LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID dispIdMember,
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accParent(
IAccessible *iface, IDispatch **ppdispParent)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accChildCount(
IAccessible *iface, LONG *pcountChildren)
{
CHECK_EXPECT(Accessible_get_accChildCount);
*pcountChildren = 1;
return S_OK;
}
static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface,
VARIANT varChildID, IDispatch **ppdispChild)
{
CHECK_EXPECT(Accessible_get_accChild);
ok(V_VT(&varChildID) == VT_I4, "V_VT(&varChildID) = %d\n", V_VT(&varChildID));
ok(V_I4(&varChildID) == 1, "V_I4(&varChildID) = %d\n", V_I4(&varChildID));
*ppdispChild = NULL;
return S_OK;
}
static HRESULT WINAPI Accessible_get_accName(IAccessible *iface,
VARIANT varID, BSTR *pszName)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accValue(IAccessible *iface,
VARIANT varID, BSTR *pszValue)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accDescription(IAccessible *iface,
VARIANT varID, BSTR *pszDescription)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface,
VARIANT varID, VARIANT *pvarRole)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accState(IAccessible *iface,
VARIANT varID, VARIANT *pvarState)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accHelp(IAccessible *iface,
VARIANT varID, BSTR *pszHelp)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accHelpTopic(IAccessible *iface,
BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface,
VARIANT varID, BSTR *pszKeyboardShortcut)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *pvarID)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accSelection(
IAccessible *iface, VARIANT *pvarID)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_get_accDefaultAction(IAccessible *iface,
VARIANT varID, BSTR *pszDefaultAction)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_accSelect(IAccessible *iface,
LONG flagsSelect, VARIANT varID)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *pxLeft,
LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface,
LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_accHitTest(IAccessible *iface,
LONG xLeft, LONG yTop, VARIANT *pvarID)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_accDoDefaultAction(
IAccessible *iface, VARIANT varID)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_put_accName(IAccessible *iface,
VARIANT varID, BSTR pszName)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI Accessible_put_accValue(IAccessible *iface,
VARIANT varID, BSTR pszValue)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static IAccessibleVtbl AccessibleVtbl = {
Accessible_QueryInterface,
Accessible_AddRef,
Accessible_Release,
Accessible_GetTypeInfoCount,
Accessible_GetTypeInfo,
Accessible_GetIDsOfNames,
Accessible_Invoke,
Accessible_get_accParent,
Accessible_get_accChildCount,
Accessible_get_accChild,
Accessible_get_accName,
Accessible_get_accValue,
Accessible_get_accDescription,
Accessible_get_accRole,
Accessible_get_accState,
Accessible_get_accHelp,
Accessible_get_accHelpTopic,
Accessible_get_accKeyboardShortcut,
Accessible_get_accFocus,
Accessible_get_accSelection,
Accessible_get_accDefaultAction,
Accessible_accSelect,
Accessible_accLocation,
Accessible_accNavigate,
Accessible_accHitTest,
Accessible_accDoDefaultAction,
Accessible_put_accName,
Accessible_put_accValue
};
static IAccessible Accessible = {&AccessibleVtbl};
static void test_getroletext(void)
{
INT ret, role;
CHAR buf[2], *buff;
WCHAR bufW[2], *buffW;
/* wrong role number */
ret = GetRoleTextA(-1, NULL, 0);
ok(ret == 0, "GetRoleTextA doesn't return zero on wrong role number, got %d\n", ret);
buf[0] = '*';
ret = GetRoleTextA(-1, buf, 2);
ok(ret == 0, "GetRoleTextA doesn't return zero on wrong role number, got %d\n", ret);
ok(buf[0] == 0, "GetRoleTextA doesn't return NULL char on wrong role number\n");
buf[0] = '*';
ret = GetRoleTextA(-1, buf, 0);
ok(ret == 0, "GetRoleTextA doesn't return zero on wrong role number, got %d\n", ret);
ok(buf[0] == '*', "GetRoleTextA modified buffer on wrong role number\n");
ret = GetRoleTextW(-1, NULL, 0);
ok(ret == 0, "GetRoleTextW doesn't return zero on wrong role number, got %d\n", ret);
bufW[0] = '*';
ret = GetRoleTextW(-1, bufW, 2);
ok(ret == 0, "GetRoleTextW doesn't return zero on wrong role number, got %d\n", ret);
ok(bufW[0] == '\0', "GetRoleTextW doesn't return NULL char on wrong role number\n");
bufW[0] = '*';
ret = GetRoleTextW(-1, bufW, 0);
ok(ret == 0, "GetRoleTextW doesn't return zero on wrong role number, got %d\n", ret);
/* zero role number - not documented */
ret = GetRoleTextA(0, NULL, 0);
ok(ret > 0, "GetRoleTextA doesn't return (>0) for zero role number, got %d\n", ret);
ret = GetRoleTextW(0, NULL, 0);
ok(ret > 0, "GetRoleTextW doesn't return (>0) for zero role number, got %d\n", ret);
/* NULL buffer, return length */
ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, NULL, 0);
ok(ret > 0, "GetRoleTextA doesn't return length on NULL buffer, got %d\n", ret);
ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, NULL, 1);
ok(ret > 0, "GetRoleTextA doesn't return length on NULL buffer, got %d\n", ret);
ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, NULL, 0);
ok(ret > 0, "GetRoleTextW doesn't return length on NULL buffer, got %d\n", ret);
ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, NULL, 1);
ok(ret > 0, "GetRoleTextW doesn't return length on NULL buffer, got %d\n", ret);
/* use a smaller buffer */
bufW[0] = '*';
ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, buf, 0);
ok(!ret, "GetRoleTextA doesn't return 0, got %d\n", ret);
ok(buf[0] == '*', "GetRoleTextA modified buffer\n");
buffW = NULL;
ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, (WCHAR*)&buffW, 0);
ok(ret, "GetRoleTextW doesn't return length\n");
ok(buffW != NULL, "GetRoleTextW doesn't modify buffer\n");
buf[0] = '*';
ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, buf, 1);
ok(ret == 0, "GetRoleTextA returned wrong length\n");
ok(buf[0] == '\0', "GetRoleTextA returned not zero-length buffer\n");
buf[0] = '*';
ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, buf, 2);
ok(!ret, "GetRoleTextA returned wrong length, got %d, expected 0\n", ret);
ok(!buf[0] || broken(buf[0]!='*') /* WinXP */,
"GetRoleTextA returned not zero-length buffer : (%c)\n", buf[0]);
bufW[0] = '*';
ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, bufW, 1);
ok(ret == 0, "GetRoleTextW returned wrong length, got %d, expected 1\n", ret);
ok(bufW[0] == '\0', "GetRoleTextW returned not zero-length buffer\n");
bufW[1] = '*';
ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, bufW, 2);
ok(ret == 1, "GetRoleTextW returned wrong length, got %d, expected 1\n", ret);
ok(bufW[1] == '\0', "GetRoleTextW returned not zero-length buffer\n");
/* use bigger buffer */
ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, NULL, 0);
buff = HeapAlloc(GetProcessHeap(), 0, 2*ret);
buff[2*ret-1] = '*';
ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, buff, 2*ret);
ok(buff[2*ret-1] == '*', "GetRoleTextA shouldn't modify this part of buffer\n");
HeapFree(GetProcessHeap(), 0, buff);
ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, NULL, 0);
buffW = HeapAlloc(GetProcessHeap(), 0, 2*ret*sizeof(WCHAR));
buffW[2*ret-1] = '*';
ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, buffW, 2*ret);
ok(buffW[2*ret-1] == '*', "GetRoleTextW shouldn't modify this part of buffer\n");
HeapFree(GetProcessHeap(), 0, buffW);
/* check returned length for all roles */
for(role = 0; role <= ROLE_SYSTEM_OUTLINEBUTTON; role++){
CHAR buff2[100];
WCHAR buff2W[100];
/* NT4 and W2K don't clear the buffer on a nonexistent role in the A-call */
memset(buff2, 0, sizeof(buff2));
ret = GetRoleTextA(role, NULL, 0);
ok(ret > 0, "Expected the role to be present\n");
GetRoleTextA(role, buff2, sizeof(buff2));
ok(ret == lstrlenA(buff2),
"GetRoleTextA: returned length doesn't match returned buffer for role %d\n", role);
/* Win98 and WinMe don't clear the buffer on a nonexistent role in the W-call */
memset(buff2W, 0, sizeof(buff2W));
ret = GetRoleTextW(role, NULL, 0);
GetRoleTextW(role, buff2W, sizeof(buff2W)/sizeof(WCHAR));
ok(ret == lstrlenW(buff2W),
"GetRoleTextW: returned length doesn't match returned buffer for role %d\n", role);
}
}
static void test_GetStateText(void)
{
WCHAR buf[1024], buf2[1024];
char bufa[1024];
void *ptr;
UINT ret, ret2;
int i;
ret2 = GetStateTextW(0, NULL, 1024);
ok(ret2, "GetStateText failed\n");
ptr = NULL;
ret = GetStateTextW(0, (WCHAR*)&ptr, 0);
ok(ret == ret2, "got %d, expected %d\n", ret, ret2);
ok(ptr != NULL, "ptr was not changed\n");
ret = GetStateTextW(0, buf, 1024);
ok(ret == ret2, "got %d, expected %d\n", ret, ret2);
ok(!memcmp(buf, ptr, ret*sizeof(WCHAR)), "got %s, expected %s\n",
wine_dbgstr_wn(buf, ret), wine_dbgstr_wn(ptr, ret));
ret = GetStateTextW(0, buf, 1);
ok(!ret, "got %d, expected 0\n", ret);
ok(!buf[0], "buf[0] = '%c'\n", buf[0]);
for(i=0; i<31; i++) {
ret = GetStateTextW(1<<i, buf, 1024);
ok(ret, "%d) GetStateText failed\n", i);
}
ret = GetStateTextW(1u<<31, buf, 1024);
ok(!ret, "31) GetStateText succeeded: %d\n", ret);
ret = GetStateTextW(2, buf, 1024);
ok(ret, "GetStateText failed\n");
ret2 = GetStateTextW(3, buf2, 1024);
ok(ret2, "GetStateText failed\n");
ok(ret == ret2, "got %d, expected %d\n", ret2, ret);
ok(!memcmp(buf, buf2, ret*sizeof(WCHAR)),
"GetStateText(2,...) returned different data than GetStateText(3,...)\n");
ret2 = GetStateTextA(0, NULL, 1024);
ok(ret2, "GetStateText failed\n");
ptr = NULL;
ret = GetStateTextA(0, (CHAR*)&ptr, 0);
ok(!ret, "got %d\n", ret);
ok(ptr == NULL, "ptr was changed\n");
ret = GetStateTextA(0, NULL, 0);
ok(ret == ret2, "got %d, expected %d\n", ret, ret2);
ret = GetStateTextA(0, bufa, 1024);
ok(ret == ret2, "got %d, expected %d\n", ret, ret2);
ret = GetStateTextA(0, bufa, 1);
ok(!ret, "got %d, expected 0\n", ret);
ok(!bufa[0], "bufa[0] = '%c'\n", bufa[0]);
for(i=0; i<31; i++) {
ret = GetStateTextA(1<<i, bufa, 1024);
ok(ret, "%d) GetStateText failed\n", i);
}
ret = GetStateTextA(1u<<31, bufa, 1024);
ok(!ret, "31) GetStateText succeeded: %d\n", ret);
}
static int Object_ref = 1;
static HRESULT WINAPI Object_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
if(IsEqualIID(riid, &IID_IUnknown)) {
*ppv = iface;
IUnknown_AddRef(iface);
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI Object_AddRef(IUnknown *iface)
{
return InterlockedIncrement(&Object_ref);
}
static ULONG WINAPI Object_Release(IUnknown *iface)
{
return InterlockedDecrement(&Object_ref);
}
static IUnknownVtbl ObjectVtbl = {
Object_QueryInterface,
Object_AddRef,
Object_Release
};
static IUnknown Object = {&ObjectVtbl};
static void test_LresultFromObject(const char *name)
{
PROCESS_INFORMATION proc;
STARTUPINFOA startup;
char cmdline[MAX_PATH];
IUnknown *unk;
HRESULT hres;
LRESULT lres;
lres = LresultFromObject(NULL, 0, 0);
ok(lres == E_INVALIDARG, "got %lx\n", lres);
hres = ObjectFromLresult(0, &IID_IUnknown, 0, (void**)&unk);
ok(hres == E_FAIL, "got %x\n", hres);
hres = ObjectFromLresult(0x10000, &IID_IUnknown, 0, (void**)&unk);
ok(hres == E_FAIL, "got %x\n", hres);
ok(Object_ref == 1, "Object_ref = %d\n", Object_ref);
lres = LresultFromObject(&IID_IUnknown, 0, &Object);
ok(SUCCEEDED(lres), "got %lx\n", lres);
ok(Object_ref > 1, "Object_ref = %d\n", Object_ref);
hres = ObjectFromLresult(lres, &IID_IUnknown, 0, (void**)&unk);
ok(hres == S_OK, "hres = %x\n", hres);
ok(unk == &Object, "unk != &Object\n");
IUnknown_Release(unk);
ok(Object_ref == 1, "Object_ref = %d\n", Object_ref);
lres = LresultFromObject(&IID_IUnknown, 0, &Object);
ok(SUCCEEDED(lres), "got %lx\n", lres);
ok(Object_ref > 1, "Object_ref = %d\n", Object_ref);
sprintf(cmdline, "\"%s\" main ObjectFromLresult %lx", name, lres);
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &proc);
winetest_wait_child_process(proc.hProcess);
ok(Object_ref == 1, "Object_ref = %d\n", Object_ref);
}
static LRESULT WINAPI test_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg) {
case WM_GETOBJECT:
if(lparam == OBJID_QUERYCLASSNAMEIDX) {
ok(!wparam, "wparam = %lx\n", wparam);
return 0;
}
ok(wparam==0xffffffff, "wparam = %lx\n", wparam);
if(lparam == (DWORD)OBJID_CURSOR)
return E_UNEXPECTED;
if(lparam == (DWORD)OBJID_CLIENT)
return LresultFromObject(&IID_IUnknown, wparam, &Object);
if(lparam == (DWORD)OBJID_WINDOW)
return 0;
ok(0, "unexpected (%ld)\n", lparam);
return 0;
}
return DefWindowProcA(hwnd, msg, wparam, lparam);
}
static BOOL register_window_class(void)
{
WNDCLASSA cls;
memset(&cls, 0, sizeof(cls));
cls.lpfnWndProc = test_window_proc;
cls.lpszClassName = "oleacc_test";
cls.hInstance = GetModuleHandleA(NULL);
return RegisterClassA(&cls);
}
static void unregister_window_class(void)
{
UnregisterClassA("oleacc_test", NULL);
}
static void test_AccessibleObjectFromWindow(void)
{
IUnknown *unk;
HRESULT hr;
HWND hwnd;
hr = AccessibleObjectFromWindow(NULL, OBJID_CURSOR, &IID_IUnknown, NULL);
ok(hr == E_INVALIDARG, "got %x\n", hr);
hr = AccessibleObjectFromWindow(NULL, OBJID_CURSOR, &IID_IUnknown, (void**)&unk);
todo_wine ok(hr == S_OK, "got %x\n", hr);
if(hr == S_OK) IUnknown_Release(unk);
hwnd = CreateWindowA("oleacc_test", "test", WS_OVERLAPPEDWINDOW,
0, 0, 0, 0, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "CreateWindow failed\n");
hr = AccessibleObjectFromWindow(hwnd, OBJID_CURSOR, &IID_IUnknown, (void**)&unk);
ok(hr == E_UNEXPECTED, "got %x\n", hr);
ok(Object_ref == 1, "Object_ref = %d\n", Object_ref);
hr = AccessibleObjectFromWindow(hwnd, OBJID_CLIENT, &IID_IUnknown, (void**)&unk);
ok(hr == S_OK, "got %x\n", hr);
ok(Object_ref == 2, "Object_ref = %d\n", Object_ref);
IUnknown_Release(unk);
DestroyWindow(hwnd);
}
static void test_GetProcessHandleFromHwnd(void)
{
HANDLE proc;
HWND hwnd;
proc = pGetProcessHandleFromHwnd(NULL);
ok(!proc, "proc = %p\n", proc);
hwnd = CreateWindowA("static", "", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "CreateWindow failed\n");
proc = pGetProcessHandleFromHwnd(hwnd);
ok(proc != NULL, "proc == NULL\n");
CloseHandle(proc);
DestroyWindow(hwnd);
}
static void test_AccessibleChildren(IAccessible *acc)
{
VARIANT children[3];
LONG count;
HRESULT hr;
count = -1;
hr = AccessibleChildren(NULL, 0, 0, children, &count);
ok(hr == E_INVALIDARG, "AccessibleChildren returned %x\n", hr);
ok(count == -1, "count = %d\n", count);
hr = AccessibleChildren(acc, 0, 0, NULL, &count);
ok(hr == E_INVALIDARG, "AccessibleChildren returned %x\n", hr);
ok(count == -1, "count = %d\n", count);
hr = AccessibleChildren(acc, 0, 0, children, NULL);
ok(hr == E_INVALIDARG, "AccessibleChildren returned %x\n", hr);
if(acc == &Accessible) {
SET_EXPECT(Accessible_QI_IEnumVARIANT);
SET_EXPECT(Accessible_get_accChildCount);
}
hr = AccessibleChildren(acc, 0, 0, children, &count);
ok(hr == S_OK, "AccessibleChildren returned %x\n", hr);
if(acc == &Accessible) {
CHECK_CALLED(Accessible_QI_IEnumVARIANT);
CHECK_CALLED(Accessible_get_accChildCount);
}
ok(!count, "count = %d\n", count);
count = -1;
if(acc == &Accessible) {
SET_EXPECT(Accessible_QI_IEnumVARIANT);
SET_EXPECT(Accessible_get_accChildCount);
}
hr = AccessibleChildren(acc, 5, 0, children, &count);
ok(hr == S_OK, "AccessibleChildren returned %x\n", hr);
if(acc == &Accessible) {
CHECK_CALLED(Accessible_QI_IEnumVARIANT);
CHECK_CALLED(Accessible_get_accChildCount);
}
ok(!count, "count = %d\n", count);
memset(children, 0xfe, sizeof(children));
V_VT(children) = VT_DISPATCH;
if(acc == &Accessible) {
SET_EXPECT(Accessible_QI_IEnumVARIANT);
SET_EXPECT(Accessible_get_accChildCount);
SET_EXPECT(Accessible_get_accChild);
}
hr = AccessibleChildren(acc, 0, 1, children, &count);
ok(hr == S_OK, "AccessibleChildren returned %x\n", hr);
if(acc == &Accessible) {
CHECK_CALLED(Accessible_QI_IEnumVARIANT);
CHECK_CALLED(Accessible_get_accChildCount);
CHECK_CALLED(Accessible_get_accChild);
ok(V_VT(children) == VT_I4, "V_VT(children) = %d\n", V_VT(children));
ok(V_I4(children) == 1, "V_I4(children) = %d\n", V_I4(children));
}else {
ok(V_VT(children) == VT_DISPATCH, "V_VT(children) = %d\n", V_VT(children));
IDispatch_Release(V_DISPATCH(children));
}
ok(count == 1, "count = %d\n", count);
if(acc == &Accessible) {
SET_EXPECT(Accessible_QI_IEnumVARIANT);
SET_EXPECT(Accessible_get_accChildCount);
SET_EXPECT(Accessible_get_accChild);
}
hr = AccessibleChildren(acc, 0, 3, children, &count);
ok(hr == S_FALSE, "AccessibleChildren returned %x\n", hr);
if(acc == &Accessible) {
CHECK_CALLED(Accessible_QI_IEnumVARIANT);
CHECK_CALLED(Accessible_get_accChildCount);
CHECK_CALLED(Accessible_get_accChild);
ok(V_VT(children) == VT_I4, "V_VT(children) = %d\n", V_VT(children));
ok(V_I4(children) == 1, "V_I4(children) = %d\n", V_I4(children));
}else {
ok(V_VT(children) == VT_DISPATCH, "V_VT(children) = %d\n", V_VT(children));
IDispatch_Release(V_DISPATCH(children));
}
ok(count == 1, "count = %d\n", count);
ok(V_VT(children+1) == VT_EMPTY, "V_VT(children+1) = %d\n", V_VT(children+1));
ok(V_VT(children+2) == VT_EMPTY, "V_VT(children+2) = %d\n", V_VT(children+2));
}
static void test_default_client_accessible_object(void)
{
static const WCHAR testW[] = {'t','e','s','t',' ','t',' ','&','j','u','n','k',0};
static const WCHAR shortcutW[] = {'A','l','t','+','t',0};
IAccessible *acc;
IDispatch *disp;
IOleWindow *ow;
IEnumVARIANT *ev;
HWND chld, hwnd, hwnd2;
HRESULT hr;
VARIANT vid, v;
BSTR str;
POINT pt;
RECT rect;
LONG l, left, top, width, height;
ULONG fetched;
hwnd = CreateWindowA("oleacc_test", "test &t &junk", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "CreateWindow failed\n");
chld = CreateWindowA("static", "message", WS_CHILD | WS_VISIBLE,
0, 0, 50, 50, hwnd, NULL, NULL, NULL);
ok(chld != NULL, "CreateWindow failed\n");
hr = CreateStdAccessibleObject(NULL, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
ok(hr == E_FAIL, "got %x\n", hr);
hr = CreateStdAccessibleObject(hwnd, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
ok(hr == S_OK, "got %x\n", hr);
hr = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void**)&ow);
ok(hr == S_OK, "got %x\n", hr);
hr = IOleWindow_GetWindow(ow, &hwnd2);
ok(hr == S_OK, "got %x\n", hr);
ok(hwnd == hwnd2, "hwnd2 = %p, expected %p\n", hwnd2, hwnd);
hr = WindowFromAccessibleObject(acc, &hwnd2);
ok(hr == S_OK, "got %x\n", hr);
ok(hwnd == hwnd2, "hwnd2 = %p, expected %p\n", hwnd2, hwnd);
IOleWindow_Release(ow);
hr = IAccessible_get_accChildCount(acc, &l);
ok(hr == S_OK, "got %x\n", hr);
ok(l == 1, "l = %d\n", l);
V_VT(&vid) = VT_I4;
V_I4(&vid) = CHILDID_SELF;
disp = (void*)0xdeadbeef;
hr = IAccessible_get_accChild(acc, vid, &disp);
ok(hr == E_INVALIDARG, "get_accChild returned %x\n", hr);
ok(disp == NULL, "disp = %p\n", disp);
V_I4(&vid) = 1;
disp = (void*)0xdeadbeef;
hr = IAccessible_get_accChild(acc, vid, &disp);
ok(hr == E_INVALIDARG, "get_accChild returned %x\n", hr);
ok(disp == NULL, "disp = %p\n", disp);
hr = IAccessible_QueryInterface(acc, &IID_IEnumVARIANT, (void**)&ev);
ok(hr == S_OK, "got %x\n", hr);
hr = IEnumVARIANT_Skip(ev, 100);
ok(hr == S_FALSE, "Skip returned %x\n", hr);
V_VT(&v) = VT_I4;
fetched = 1;
hr = IEnumVARIANT_Next(ev, 1, &v, &fetched);
ok(hr == S_FALSE, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(fetched == 0, "fetched = %d\n", fetched);
hr = IEnumVARIANT_Reset(ev);
ok(hr == S_OK, "got %x\n", hr);
V_VT(&v) = VT_I4;
fetched = 2;
hr = IEnumVARIANT_Next(ev, 1, &v, &fetched);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_DISPATCH, "V_VT(&v) = %d\n", V_VT(&v));
IDispatch_Release(V_DISPATCH(&v));
ok(fetched == 1, "fetched = %d\n", fetched);
IEnumVARIANT_Release(ev);
test_AccessibleChildren(acc);
V_VT(&vid) = VT_I4;
V_I4(&vid) = CHILDID_SELF;
hr = IAccessible_get_accName(acc, vid, &str);
ok(hr == S_OK, "got %x\n", hr);
ok(!lstrcmpW(str, testW), "name = %s\n", wine_dbgstr_w(str));
SysFreeString(str);
V_I4(&vid) = 1;
str = (void*)0xdeadbeef;
hr = IAccessible_get_accName(acc, vid, &str);
ok(hr == E_INVALIDARG, "got %x\n", hr);
ok(!str, "str != NULL\n");
V_I4(&vid) = CHILDID_SELF;
str = (void*)0xdeadbeef;
hr = IAccessible_get_accValue(acc, vid, &str);
ok(hr == S_FALSE, "got %x\n", hr);
ok(!str, "str != NULL\n");
str = (void*)0xdeadbeef;
hr = IAccessible_get_accDescription(acc, vid, &str);
ok(hr == S_FALSE, "got %x\n", hr);
ok(!str, "str != NULL\n");
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = (void*)0xdeadbeef;
hr = IAccessible_get_accRole(acc, vid, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == ROLE_SYSTEM_CLIENT, "V_I4(&v) = %d\n", V_I4(&v));
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = (void*)0xdeadbeef;
hr = IAccessible_get_accState(acc, vid, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == (STATE_SYSTEM_FOCUSABLE|STATE_SYSTEM_INVISIBLE),
"V_I4(&v) = %x\n", V_I4(&v));
str = (void*)0xdeadbeef;
hr = IAccessible_get_accHelp(acc, vid, &str);
ok(hr == S_FALSE, "got %x\n", hr);
ok(!str, "str != NULL\n");
hr = IAccessible_get_accKeyboardShortcut(acc, vid, &str);
ok(hr == S_OK, "got %x\n", hr);
ok(!lstrcmpW(str, shortcutW), "str = %s\n", wine_dbgstr_w(str));
SysFreeString(str);
str = (void*)0xdeadbeef;
hr = IAccessible_get_accDefaultAction(acc, vid, &str);
ok(hr == S_FALSE, "got %x\n", hr);
ok(!str, "str != NULL\n");
pt.x = pt.y = 60;
ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
pt.x = pt.y = 25;
ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
ShowWindow(hwnd, TRUE);
pt.x = pt.y = 60;
ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
pt.x = pt.y = 25;
ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_DISPATCH, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(&v) = %p\n", V_DISPATCH(&v));
VariantClear(&v);
ShowWindow(chld, FALSE);
pt.x = pt.y = 25;
ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
hr = IAccessible_get_accParent(acc, &disp);
ok(hr == S_OK, "got %x\n", hr);
ok(disp != NULL, "disp == NULL\n");
IDispatch_Release(disp);
ok(GetClientRect(hwnd, &rect), "GetClientRect failed\n");
pt.x = rect.left;
pt.y = rect.top;
MapWindowPoints(hwnd, NULL, &pt, 1);
rect.left = pt.x;
rect.top = pt.y;
pt.x = rect.right;
pt.y = rect.bottom;
MapWindowPoints(hwnd, NULL, &pt, 1);
hr = IAccessible_accLocation(acc, &left, &top, &width, &height, vid);
ok(hr == S_OK, "got %x\n", hr);
ok(left == rect.left, "left = %d, expected %d\n", left, rect.left);
ok(top == rect.top, "top = %d, expected %d\n", top, rect.top);
ok(width == pt.x-rect.left, "width = %d, expected %d\n", width, pt.x-rect.left);
ok(height == pt.y-rect.top, "height = %d, expected %d\n", height, pt.y-rect.top);
DestroyWindow(hwnd);
hr = IAccessible_get_accChildCount(acc, &l);
ok(hr == S_OK, "got %x\n", hr);
ok(l == 0, "l = %d\n", l);
hr = IAccessible_get_accName(acc, vid, &str);
ok(hr == E_INVALIDARG, "got %x\n", hr);
hr = IAccessible_get_accValue(acc, vid, &str);
ok(hr == S_FALSE, "got %x\n", hr);
hr = IAccessible_get_accRole(acc, vid, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == ROLE_SYSTEM_CLIENT, "V_I4(&v) = %d\n", V_I4(&v));
hr = IAccessible_get_accState(acc, vid, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == STATE_SYSTEM_INVISIBLE, "V_I4(&v) = %x\n", V_I4(&v));
hr = IAccessible_accHitTest(acc, 200, 200, &v);
ok(hr == S_OK, "got %x\n", hr);
ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
disp = (void*)0xdeadbeef;
hr = IAccessible_get_accParent(acc, &disp);
ok(hr == E_FAIL, "got %x\n", hr);
ok(disp == NULL, "disp = %p\n", disp);
hr = IAccessible_accLocation(acc, &left, &top, &width, &height, vid);
ok(hr == S_OK, "got %x\n", hr);
ok(left == 0, "left = %d\n", left);
ok(top == 0, "top = %d\n", top);
ok(width == 0, "width = %d\n", width);
ok(height == 0, "height = %d\n", height);
IAccessible_Release(acc);
}
static void test_CAccPropServices(void)
{
IAccPropServices *acc_prop_services;
HRESULT hres;
hres = CoCreateInstance(&CLSID_CAccPropServices, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
&IID_IAccPropServices, (void**)&acc_prop_services);
ok(hres == S_OK, "Could not create CAccPropServices instance: %08x\n", hres);
IAccPropServices_Release(acc_prop_services);
}
START_TEST(main)
{
int argc;
char **argv;
if(!init())
return;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
argc = winetest_get_mainargs(&argv);
if(argc == 4 && !strcmp(argv[2], "ObjectFromLresult")) {
IUnknown *unk;
HRESULT hres;
LRESULT lres;
sscanf(argv[3], "%lx", &lres);
hres = ObjectFromLresult(lres, &IID_IUnknown, 0, (void**)&unk);
ok(hres == S_OK, "hres = %x\n", hres);
IUnknown_Release(unk);
CoUninitialize();
return;
}
if(!register_window_class()) {
skip("can't register test window class\n");
return;
}
test_getroletext();
test_GetStateText();
test_LresultFromObject(argv[0]);
test_AccessibleObjectFromWindow();
test_GetProcessHandleFromHwnd();
test_default_client_accessible_object();
test_AccessibleChildren(&Accessible);
unregister_window_class();
CoUninitialize();
CoInitialize(NULL);
test_CAccPropServices();
CoUninitialize();
}