1 /*
2  * oleacc tests
3  *
4  * Copyright 2008 Nikolay Sivov
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define COBJMACROS
22 
23 #include "wine/test.h"
24 #include <stdio.h>
25 
26 #include "initguid.h"
27 #include <oleacc.h>
28 
29 #define DEFINE_EXPECT(func) \
30     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
31 
32 #define SET_EXPECT(func) \
33     do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
34 
35 #define CHECK_EXPECT2(func) \
36     do { \
37         ok(expect_ ##func, "unexpected call " #func "\n"); \
38         called_ ## func = TRUE; \
39     }while(0)
40 
41 #define CHECK_EXPECT(func) \
42     do { \
43         CHECK_EXPECT2(func); \
44         expect_ ## func = FALSE; \
45     }while(0)
46 
47 #define CHECK_CALLED(func) \
48     do { \
49         ok(called_ ## func, "expected " #func "\n"); \
50         expect_ ## func = called_ ## func = FALSE; \
51     }while(0)
52 
53 DEFINE_EXPECT(Accessible_QI_IEnumVARIANT);
54 DEFINE_EXPECT(Accessible_get_accChildCount);
55 DEFINE_EXPECT(Accessible_get_accChild);
56 
57 static HANDLE (WINAPI *pGetProcessHandleFromHwnd)(HWND);
58 
59 static BOOL init(void)
60 {
61     HMODULE oleacc = GetModuleHandleA("oleacc.dll");
62 
63     pGetProcessHandleFromHwnd = (void*)GetProcAddress(oleacc, "GetProcessHandleFromHwnd");
64     if(!pGetProcessHandleFromHwnd) {
65         win_skip("GetProcessHandleFromHwnd not available\n");
66         return FALSE;
67     }
68 
69     return TRUE;
70 }
71 
72 static HRESULT WINAPI Accessible_QueryInterface(
73         IAccessible *iface, REFIID riid, void **ppvObject)
74 {
75     if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
76         CHECK_EXPECT(Accessible_QI_IEnumVARIANT);
77         return E_NOINTERFACE;
78     }
79 
80     ok(0, "unexpected QI call: %s\n", wine_dbgstr_guid(riid));
81     return E_NOTIMPL;
82 }
83 
84 static ULONG WINAPI Accessible_AddRef(IAccessible *iface)
85 {
86     return 2;
87 }
88 
89 static ULONG WINAPI Accessible_Release(IAccessible *iface)
90 {
91     return 1;
92 }
93 
94 static HRESULT WINAPI Accessible_GetTypeInfoCount(
95         IAccessible *iface, UINT *pctinfo)
96 {
97     ok(0, "unexpected call\n");
98     return E_NOTIMPL;
99 }
100 
101 static HRESULT WINAPI Accessible_GetTypeInfo(IAccessible *iface,
102         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
103 {
104     ok(0, "unexpected call\n");
105     return E_NOTIMPL;
106 }
107 
108 static HRESULT WINAPI Accessible_GetIDsOfNames(IAccessible *iface, REFIID riid,
109         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
110 {
111     ok(0, "unexpected call\n");
112     return E_NOTIMPL;
113 }
114 
115 static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID dispIdMember,
116         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
117         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
118 {
119     ok(0, "unexpected call\n");
120     return E_NOTIMPL;
121 }
122 
123 static HRESULT WINAPI Accessible_get_accParent(
124         IAccessible *iface, IDispatch **ppdispParent)
125 {
126     ok(0, "unexpected call\n");
127     return E_NOTIMPL;
128 }
129 
130 static HRESULT WINAPI Accessible_get_accChildCount(
131         IAccessible *iface, LONG *pcountChildren)
132 {
133     CHECK_EXPECT(Accessible_get_accChildCount);
134     *pcountChildren = 1;
135     return S_OK;
136 }
137 
138 static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface,
139         VARIANT varChildID, IDispatch **ppdispChild)
140 {
141     CHECK_EXPECT(Accessible_get_accChild);
142     ok(V_VT(&varChildID) == VT_I4, "V_VT(&varChildID) = %d\n", V_VT(&varChildID));
143     ok(V_I4(&varChildID) == 1, "V_I4(&varChildID) = %d\n", V_I4(&varChildID));
144 
145     *ppdispChild = NULL;
146     return S_OK;
147 }
148 
149 static HRESULT WINAPI Accessible_get_accName(IAccessible *iface,
150         VARIANT varID, BSTR *pszName)
151 {
152     ok(0, "unexpected call\n");
153     return E_NOTIMPL;
154 }
155 
156 static HRESULT WINAPI Accessible_get_accValue(IAccessible *iface,
157         VARIANT varID, BSTR *pszValue)
158 {
159     ok(0, "unexpected call\n");
160     return E_NOTIMPL;
161 }
162 
163 static HRESULT WINAPI Accessible_get_accDescription(IAccessible *iface,
164         VARIANT varID, BSTR *pszDescription)
165 {
166     ok(0, "unexpected call\n");
167     return E_NOTIMPL;
168 }
169 
170 static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface,
171         VARIANT varID, VARIANT *pvarRole)
172 {
173     ok(0, "unexpected call\n");
174     return E_NOTIMPL;
175 }
176 
177 static HRESULT WINAPI Accessible_get_accState(IAccessible *iface,
178         VARIANT varID, VARIANT *pvarState)
179 {
180     ok(0, "unexpected call\n");
181     return E_NOTIMPL;
182 }
183 
184 static HRESULT WINAPI Accessible_get_accHelp(IAccessible *iface,
185         VARIANT varID, BSTR *pszHelp)
186 {
187     ok(0, "unexpected call\n");
188     return E_NOTIMPL;
189 }
190 
191 static HRESULT WINAPI Accessible_get_accHelpTopic(IAccessible *iface,
192         BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic)
193 {
194     ok(0, "unexpected call\n");
195     return E_NOTIMPL;
196 }
197 
198 static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface,
199         VARIANT varID, BSTR *pszKeyboardShortcut)
200 {
201     ok(0, "unexpected call\n");
202     return E_NOTIMPL;
203 }
204 
205 static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *pvarID)
206 {
207     ok(0, "unexpected call\n");
208     return E_NOTIMPL;
209 }
210 
211 static HRESULT WINAPI Accessible_get_accSelection(
212         IAccessible *iface, VARIANT *pvarID)
213 {
214     ok(0, "unexpected call\n");
215     return E_NOTIMPL;
216 }
217 
218 static HRESULT WINAPI Accessible_get_accDefaultAction(IAccessible *iface,
219         VARIANT varID, BSTR *pszDefaultAction)
220 {
221     ok(0, "unexpected call\n");
222     return E_NOTIMPL;
223 }
224 
225 static HRESULT WINAPI Accessible_accSelect(IAccessible *iface,
226         LONG flagsSelect, VARIANT varID)
227 {
228     ok(0, "unexpected call\n");
229     return E_NOTIMPL;
230 }
231 
232 static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *pxLeft,
233         LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID)
234 {
235     ok(0, "unexpected call\n");
236     return E_NOTIMPL;
237 }
238 
239 static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface,
240         LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
241 {
242     ok(0, "unexpected call\n");
243     return E_NOTIMPL;
244 }
245 
246 static HRESULT WINAPI Accessible_accHitTest(IAccessible *iface,
247         LONG xLeft, LONG yTop, VARIANT *pvarID)
248 {
249     ok(0, "unexpected call\n");
250     return E_NOTIMPL;
251 }
252 
253 static HRESULT WINAPI Accessible_accDoDefaultAction(
254         IAccessible *iface, VARIANT varID)
255 {
256     ok(0, "unexpected call\n");
257     return E_NOTIMPL;
258 }
259 
260 static HRESULT WINAPI Accessible_put_accName(IAccessible *iface,
261         VARIANT varID, BSTR pszName)
262 {
263     ok(0, "unexpected call\n");
264     return E_NOTIMPL;
265 }
266 
267 static HRESULT WINAPI Accessible_put_accValue(IAccessible *iface,
268         VARIANT varID, BSTR pszValue)
269 {
270     ok(0, "unexpected call\n");
271     return E_NOTIMPL;
272 }
273 
274 static IAccessibleVtbl AccessibleVtbl = {
275     Accessible_QueryInterface,
276     Accessible_AddRef,
277     Accessible_Release,
278     Accessible_GetTypeInfoCount,
279     Accessible_GetTypeInfo,
280     Accessible_GetIDsOfNames,
281     Accessible_Invoke,
282     Accessible_get_accParent,
283     Accessible_get_accChildCount,
284     Accessible_get_accChild,
285     Accessible_get_accName,
286     Accessible_get_accValue,
287     Accessible_get_accDescription,
288     Accessible_get_accRole,
289     Accessible_get_accState,
290     Accessible_get_accHelp,
291     Accessible_get_accHelpTopic,
292     Accessible_get_accKeyboardShortcut,
293     Accessible_get_accFocus,
294     Accessible_get_accSelection,
295     Accessible_get_accDefaultAction,
296     Accessible_accSelect,
297     Accessible_accLocation,
298     Accessible_accNavigate,
299     Accessible_accHitTest,
300     Accessible_accDoDefaultAction,
301     Accessible_put_accName,
302     Accessible_put_accValue
303 };
304 
305 static IAccessible Accessible = {&AccessibleVtbl};
306 
307 static void test_getroletext(void)
308 {
309     INT ret, role;
310     CHAR buf[2], *buff;
311     WCHAR bufW[2], *buffW;
312 
313     /* wrong role number */
314     ret = GetRoleTextA(-1, NULL, 0);
315     ok(ret == 0, "GetRoleTextA doesn't return zero on wrong role number, got %d\n", ret);
316     buf[0] = '*';
317     ret = GetRoleTextA(-1, buf, 2);
318     ok(ret == 0, "GetRoleTextA doesn't return zero on wrong role number, got %d\n", ret);
319     ok(buf[0] == 0, "GetRoleTextA doesn't return NULL char on wrong role number\n");
320     buf[0] = '*';
321     ret = GetRoleTextA(-1, buf, 0);
322     ok(ret == 0, "GetRoleTextA doesn't return zero on wrong role number, got %d\n", ret);
323     ok(buf[0] == '*', "GetRoleTextA modified buffer on wrong role number\n");
324 
325     ret = GetRoleTextW(-1, NULL, 0);
326     ok(ret == 0, "GetRoleTextW doesn't return zero on wrong role number, got %d\n", ret);
327     bufW[0] = '*';
328     ret = GetRoleTextW(-1, bufW, 2);
329     ok(ret == 0, "GetRoleTextW doesn't return zero on wrong role number, got %d\n", ret);
330     ok(bufW[0] == '\0', "GetRoleTextW doesn't return NULL char on wrong role number\n");
331     bufW[0] = '*';
332     ret = GetRoleTextW(-1, bufW, 0);
333     ok(ret == 0, "GetRoleTextW doesn't return zero on wrong role number, got %d\n", ret);
334 
335     /* zero role number - not documented */
336     ret = GetRoleTextA(0, NULL, 0);
337     ok(ret > 0, "GetRoleTextA doesn't return (>0) for zero role number, got %d\n", ret);
338     ret = GetRoleTextW(0, NULL, 0);
339     ok(ret > 0, "GetRoleTextW doesn't return (>0) for zero role number, got %d\n", ret);
340 
341     /* NULL buffer, return length */
342     ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, NULL, 0);
343     ok(ret > 0, "GetRoleTextA doesn't return length on NULL buffer, got %d\n", ret);
344     ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, NULL, 1);
345     ok(ret > 0, "GetRoleTextA doesn't return length on NULL buffer, got %d\n", ret);
346     ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, NULL, 0);
347     ok(ret > 0, "GetRoleTextW doesn't return length on NULL buffer, got %d\n", ret);
348     ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, NULL, 1);
349     ok(ret > 0, "GetRoleTextW doesn't return length on NULL buffer, got %d\n", ret);
350 
351     /* use a smaller buffer */
352     bufW[0] = '*';
353     ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, buf, 0);
354     ok(!ret, "GetRoleTextA doesn't return 0, got %d\n", ret);
355     ok(buf[0] == '*', "GetRoleTextA modified buffer\n");
356     buffW = NULL;
357     ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, (WCHAR*)&buffW, 0);
358     ok(ret, "GetRoleTextW doesn't return length\n");
359     ok(buffW != NULL, "GetRoleTextW doesn't modify buffer\n");
360     buf[0] = '*';
361     ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, buf, 1);
362     ok(ret == 0, "GetRoleTextA returned wrong length\n");
363     ok(buf[0] == '\0', "GetRoleTextA returned not zero-length buffer\n");
364     buf[0] = '*';
365     ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, buf, 2);
366     ok(!ret, "GetRoleTextA returned wrong length, got %d, expected 0\n", ret);
367     ok(!buf[0] || broken(buf[0]!='*') /* WinXP */,
368             "GetRoleTextA returned not zero-length buffer : (%c)\n", buf[0]);
369 
370     bufW[0] = '*';
371     ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, bufW, 1);
372     ok(ret == 0, "GetRoleTextW returned wrong length, got %d, expected 1\n", ret);
373     ok(bufW[0] == '\0', "GetRoleTextW returned not zero-length buffer\n");
374     bufW[1] = '*';
375     ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, bufW, 2);
376     ok(ret == 1, "GetRoleTextW returned wrong length, got %d, expected 1\n", ret);
377     ok(bufW[1] == '\0', "GetRoleTextW returned not zero-length buffer\n");
378 
379     /* use bigger buffer */
380     ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, NULL, 0);
381     buff = HeapAlloc(GetProcessHeap(), 0, 2*ret);
382     buff[2*ret-1] = '*';
383     ret = GetRoleTextA(ROLE_SYSTEM_TITLEBAR, buff, 2*ret);
384     ok(buff[2*ret-1] == '*', "GetRoleTextA shouldn't modify this part of buffer\n");
385     HeapFree(GetProcessHeap(), 0, buff);
386 
387     ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, NULL, 0);
388     buffW = HeapAlloc(GetProcessHeap(), 0, 2*ret*sizeof(WCHAR));
389     buffW[2*ret-1] = '*';
390     ret = GetRoleTextW(ROLE_SYSTEM_TITLEBAR, buffW, 2*ret);
391     ok(buffW[2*ret-1] == '*', "GetRoleTextW shouldn't modify this part of buffer\n");
392     HeapFree(GetProcessHeap(), 0, buffW);
393 
394     /* check returned length for all roles */
395     for(role = 0; role <= ROLE_SYSTEM_OUTLINEBUTTON; role++){
396         CHAR buff2[100];
397         WCHAR buff2W[100];
398 
399         /* NT4 and W2K don't clear the buffer on a nonexistent role in the A-call */
400         memset(buff2, 0, sizeof(buff2));
401 
402         ret = GetRoleTextA(role, NULL, 0);
403         ok(ret > 0, "Expected the role to be present\n");
404 
405         GetRoleTextA(role, buff2, sizeof(buff2));
406         ok(ret == lstrlenA(buff2),
407            "GetRoleTextA: returned length doesn't match returned buffer for role %d\n", role);
408 
409         /* Win98 and WinMe don't clear the buffer on a nonexistent role in the W-call */
410         memset(buff2W, 0, sizeof(buff2W));
411 
412         ret = GetRoleTextW(role, NULL, 0);
413         GetRoleTextW(role, buff2W, ARRAY_SIZE(buff2W));
414         ok(ret == lstrlenW(buff2W),
415            "GetRoleTextW: returned length doesn't match returned buffer for role %d\n", role);
416     }
417 }
418 
419 static void test_GetStateText(void)
420 {
421     WCHAR buf[1024], buf2[1024];
422     char bufa[1024];
423     void *ptr;
424     UINT ret, ret2;
425     int i;
426 
427     ret2 = GetStateTextW(0, NULL, 1024);
428     ok(ret2, "GetStateText failed\n");
429 
430     ptr = NULL;
431     ret = GetStateTextW(0, (WCHAR*)&ptr, 0);
432     ok(ret == ret2, "got %d, expected %d\n", ret, ret2);
433     ok(ptr != NULL, "ptr was not changed\n");
434 
435     ret = GetStateTextW(0, buf, 1024);
436     ok(ret == ret2, "got %d, expected %d\n", ret, ret2);
437     ok(!memcmp(buf, ptr, ret*sizeof(WCHAR)), "got %s, expected %s\n",
438             wine_dbgstr_wn(buf, ret), wine_dbgstr_wn(ptr, ret));
439 
440     ret = GetStateTextW(0, buf, 1);
441     ok(!ret, "got %d, expected 0\n", ret);
442     ok(!buf[0], "buf[0] = '%c'\n", buf[0]);
443 
444     for(i=0; i<31; i++) {
445         ret = GetStateTextW(1<<i, buf, 1024);
446         ok(ret, "%d) GetStateText failed\n", i);
447     }
448     ret = GetStateTextW(1u<<31, buf, 1024);
449     ok(!ret, "31) GetStateText succeeded: %d\n", ret);
450 
451     ret = GetStateTextW(2, buf, 1024);
452     ok(ret, "GetStateText failed\n");
453     ret2 = GetStateTextW(3, buf2, 1024);
454     ok(ret2, "GetStateText failed\n");
455     ok(ret == ret2, "got %d, expected %d\n", ret2, ret);
456     ok(!memcmp(buf, buf2, ret*sizeof(WCHAR)),
457             "GetStateText(2,...) returned different data than GetStateText(3,...)\n");
458 
459     ret2 = GetStateTextA(0, NULL, 1024);
460     ok(ret2, "GetStateText failed\n");
461 
462     ptr = NULL;
463     ret = GetStateTextA(0, (CHAR*)&ptr, 0);
464     ok(!ret, "got %d\n", ret);
465     ok(ptr == NULL, "ptr was changed\n");
466 
467     ret = GetStateTextA(0, NULL, 0);
468     ok(ret == ret2, "got %d, expected %d\n", ret, ret2);
469 
470     ret = GetStateTextA(0, bufa, 1024);
471     ok(ret == ret2, "got %d, expected %d\n", ret, ret2);
472 
473     ret = GetStateTextA(0, bufa, 1);
474     ok(!ret, "got %d, expected 0\n", ret);
475     ok(!bufa[0], "bufa[0] = '%c'\n", bufa[0]);
476 
477     for(i=0; i<31; i++) {
478         ret = GetStateTextA(1<<i, bufa, 1024);
479         ok(ret, "%d) GetStateText failed\n", i);
480     }
481     ret = GetStateTextA(1u<<31, bufa, 1024);
482     ok(!ret, "31) GetStateText succeeded: %d\n", ret);
483 }
484 
485 static int Object_ref = 1;
486 static HRESULT WINAPI Object_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
487 {
488     if(IsEqualIID(riid, &IID_IUnknown)) {
489         *ppv = iface;
490         IUnknown_AddRef(iface);
491         return S_OK;
492     }
493     return E_NOINTERFACE;
494 }
495 
496 static ULONG WINAPI Object_AddRef(IUnknown *iface)
497 {
498     return InterlockedIncrement(&Object_ref);
499 }
500 
501 static ULONG WINAPI Object_Release(IUnknown *iface)
502 {
503     return InterlockedDecrement(&Object_ref);
504 }
505 
506 static IUnknownVtbl ObjectVtbl = {
507     Object_QueryInterface,
508     Object_AddRef,
509     Object_Release
510 };
511 
512 static IUnknown Object = {&ObjectVtbl};
513 
514 static void test_LresultFromObject(const char *name)
515 {
516     PROCESS_INFORMATION proc;
517     STARTUPINFOA startup;
518     char cmdline[MAX_PATH];
519     IUnknown *unk;
520     HRESULT hres;
521     LRESULT lres;
522 
523     lres = LresultFromObject(NULL, 0, 0);
524     ok(lres == E_INVALIDARG, "got %lx\n", lres);
525 
526     hres = ObjectFromLresult(0, &IID_IUnknown, 0, (void**)&unk);
527     ok(hres == E_FAIL, "got %x\n", hres);
528     hres = ObjectFromLresult(0x10000, &IID_IUnknown, 0, (void**)&unk);
529     ok(hres == E_FAIL, "got %x\n", hres);
530 
531     ok(Object_ref == 1, "Object_ref = %d\n", Object_ref);
532     lres = LresultFromObject(&IID_IUnknown, 0, &Object);
533     ok(SUCCEEDED(lres), "got %lx\n", lres);
534     ok(Object_ref > 1, "Object_ref = %d\n", Object_ref);
535 
536     hres = ObjectFromLresult(lres, &IID_IUnknown, 0, (void**)&unk);
537     ok(hres == S_OK, "hres = %x\n", hres);
538     ok(unk == &Object, "unk != &Object\n");
539     IUnknown_Release(unk);
540     ok(Object_ref == 1, "Object_ref = %d\n", Object_ref);
541 
542     lres = LresultFromObject(&IID_IUnknown, 0, &Object);
543     ok(SUCCEEDED(lres), "got %lx\n", lres);
544     ok(Object_ref > 1, "Object_ref = %d\n", Object_ref);
545 
546     sprintf(cmdline, "\"%s\" main ObjectFromLresult %s", name, wine_dbgstr_longlong(lres));
547     memset(&startup, 0, sizeof(startup));
548     startup.cb = sizeof(startup);
549     CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &proc);
550     winetest_wait_child_process(proc.hProcess);
551     ok(Object_ref == 1, "Object_ref = %d\n", Object_ref);
552 }
553 
554 static LRESULT WINAPI test_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
555 {
556     switch(msg) {
557     case WM_GETOBJECT:
558         if(lparam == OBJID_QUERYCLASSNAMEIDX) {
559             ok(!wparam, "wparam = %lx\n", wparam);
560             return 0;
561         }
562 
563         ok(wparam==0xffffffff, "wparam = %lx\n", wparam);
564         if(lparam == (DWORD)OBJID_CURSOR)
565             return E_UNEXPECTED;
566         if(lparam == (DWORD)OBJID_CLIENT)
567             return LresultFromObject(&IID_IUnknown, wparam, &Object);
568         if(lparam == (DWORD)OBJID_WINDOW)
569             return 0;
570 
571         ok(0, "unexpected (%ld)\n", lparam);
572         return 0;
573     }
574 
575     return DefWindowProcA(hwnd, msg, wparam, lparam);
576 }
577 
578 static BOOL register_window_class(void)
579 {
580     WNDCLASSA cls;
581 
582     memset(&cls, 0, sizeof(cls));
583     cls.lpfnWndProc = test_window_proc;
584     cls.lpszClassName = "oleacc_test";
585     cls.hInstance = GetModuleHandleA(NULL);
586 
587     return RegisterClassA(&cls);
588 }
589 
590 static void unregister_window_class(void)
591 {
592     UnregisterClassA("oleacc_test", NULL);
593 }
594 
595 static void test_AccessibleObjectFromWindow(void)
596 {
597     IUnknown *unk;
598     HRESULT hr;
599     HWND hwnd;
600 
601     hr = AccessibleObjectFromWindow(NULL, OBJID_CURSOR, &IID_IUnknown, NULL);
602     ok(hr == E_INVALIDARG, "got %x\n", hr);
603 
604     hr = AccessibleObjectFromWindow(NULL, OBJID_CURSOR, &IID_IUnknown, (void**)&unk);
605     todo_wine ok(hr == S_OK, "got %x\n", hr);
606     if(hr == S_OK) IUnknown_Release(unk);
607 
608     hwnd = CreateWindowA("oleacc_test", "test", WS_OVERLAPPEDWINDOW,
609             0, 0, 0, 0, NULL, NULL, NULL, NULL);
610     ok(hwnd != NULL, "CreateWindow failed\n");
611 
612     hr = AccessibleObjectFromWindow(hwnd, OBJID_CURSOR, &IID_IUnknown, (void**)&unk);
613     ok(hr == E_UNEXPECTED, "got %x\n", hr);
614 
615     ok(Object_ref == 1, "Object_ref = %d\n", Object_ref);
616     hr = AccessibleObjectFromWindow(hwnd, OBJID_CLIENT, &IID_IUnknown, (void**)&unk);
617     ok(hr == S_OK, "got %x\n", hr);
618     ok(Object_ref == 2, "Object_ref = %d\n", Object_ref);
619     IUnknown_Release(unk);
620 
621     DestroyWindow(hwnd);
622 }
623 
624 static void test_GetProcessHandleFromHwnd(void)
625 {
626     HANDLE proc;
627     HWND hwnd;
628 
629     proc = pGetProcessHandleFromHwnd(NULL);
630     ok(!proc, "proc = %p\n", proc);
631 
632     hwnd = CreateWindowA("static", "", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
633     ok(hwnd != NULL, "CreateWindow failed\n");
634 
635     proc = pGetProcessHandleFromHwnd(hwnd);
636     ok(proc != NULL, "proc == NULL\n");
637     CloseHandle(proc);
638 
639     DestroyWindow(hwnd);
640 }
641 
642 static void test_AccessibleChildren(IAccessible *acc)
643 {
644     VARIANT children[3];
645     LONG count;
646     HRESULT hr;
647 
648     count = -1;
649     hr = AccessibleChildren(NULL, 0, 0, children, &count);
650     ok(hr == E_INVALIDARG, "AccessibleChildren returned %x\n", hr);
651     ok(count == -1, "count = %d\n", count);
652     hr = AccessibleChildren(acc, 0, 0, NULL, &count);
653     ok(hr == E_INVALIDARG, "AccessibleChildren returned %x\n", hr);
654     ok(count == -1, "count = %d\n", count);
655     hr = AccessibleChildren(acc, 0, 0, children, NULL);
656     ok(hr == E_INVALIDARG, "AccessibleChildren returned %x\n", hr);
657 
658     if(acc == &Accessible) {
659         SET_EXPECT(Accessible_QI_IEnumVARIANT);
660         SET_EXPECT(Accessible_get_accChildCount);
661     }
662     hr = AccessibleChildren(acc, 0, 0, children, &count);
663     ok(hr == S_OK, "AccessibleChildren returned %x\n", hr);
664     if(acc == &Accessible) {
665         CHECK_CALLED(Accessible_QI_IEnumVARIANT);
666         CHECK_CALLED(Accessible_get_accChildCount);
667     }
668     ok(!count, "count = %d\n", count);
669     count = -1;
670     if(acc == &Accessible) {
671         SET_EXPECT(Accessible_QI_IEnumVARIANT);
672         SET_EXPECT(Accessible_get_accChildCount);
673     }
674     hr = AccessibleChildren(acc, 5, 0, children, &count);
675     ok(hr == S_OK, "AccessibleChildren returned %x\n", hr);
676     if(acc == &Accessible) {
677         CHECK_CALLED(Accessible_QI_IEnumVARIANT);
678         CHECK_CALLED(Accessible_get_accChildCount);
679     }
680     ok(!count, "count = %d\n", count);
681 
682     memset(children, 0xfe, sizeof(children));
683     V_VT(children) = VT_DISPATCH;
684     if(acc == &Accessible) {
685         SET_EXPECT(Accessible_QI_IEnumVARIANT);
686         SET_EXPECT(Accessible_get_accChildCount);
687         SET_EXPECT(Accessible_get_accChild);
688     }
689     hr = AccessibleChildren(acc, 0, 1, children, &count);
690     ok(hr == S_OK, "AccessibleChildren returned %x\n", hr);
691     if(acc == &Accessible) {
692         CHECK_CALLED(Accessible_QI_IEnumVARIANT);
693         CHECK_CALLED(Accessible_get_accChildCount);
694         CHECK_CALLED(Accessible_get_accChild);
695 
696         ok(V_VT(children) == VT_I4, "V_VT(children) = %d\n", V_VT(children));
697         ok(V_I4(children) == 1, "V_I4(children) = %d\n", V_I4(children));
698     }else {
699         ok(V_VT(children) == VT_DISPATCH, "V_VT(children) = %d\n", V_VT(children));
700         IDispatch_Release(V_DISPATCH(children));
701     }
702     ok(count == 1, "count = %d\n", count);
703 
704     if(acc == &Accessible) {
705         SET_EXPECT(Accessible_QI_IEnumVARIANT);
706         SET_EXPECT(Accessible_get_accChildCount);
707         SET_EXPECT(Accessible_get_accChild);
708     }
709     hr = AccessibleChildren(acc, 0, 3, children, &count);
710     ok(hr == S_FALSE, "AccessibleChildren returned %x\n", hr);
711     if(acc == &Accessible) {
712         CHECK_CALLED(Accessible_QI_IEnumVARIANT);
713         CHECK_CALLED(Accessible_get_accChildCount);
714         CHECK_CALLED(Accessible_get_accChild);
715 
716         ok(V_VT(children) == VT_I4, "V_VT(children) = %d\n", V_VT(children));
717         ok(V_I4(children) == 1, "V_I4(children) = %d\n", V_I4(children));
718     }else {
719         ok(V_VT(children) == VT_DISPATCH, "V_VT(children) = %d\n", V_VT(children));
720         IDispatch_Release(V_DISPATCH(children));
721     }
722     ok(count == 1, "count = %d\n", count);
723     ok(V_VT(children+1) == VT_EMPTY, "V_VT(children+1) = %d\n", V_VT(children+1));
724     ok(V_VT(children+2) == VT_EMPTY, "V_VT(children+2) = %d\n", V_VT(children+2));
725 }
726 
727 static void test_default_client_accessible_object(void)
728 {
729     static const WCHAR testW[] = {'t','e','s','t',' ','t',' ','&','j','u','n','k',0};
730     static const WCHAR shortcutW[] = {'A','l','t','+','t',0};
731 
732     IAccessible *acc;
733     IDispatch *disp;
734     IOleWindow *ow;
735     IEnumVARIANT *ev;
736     HWND chld, hwnd, hwnd2;
737     HRESULT hr;
738     VARIANT vid, v;
739     BSTR str;
740     POINT pt;
741     RECT rect;
742     LONG l, left, top, width, height;
743     ULONG fetched;
744 
745     hwnd = CreateWindowA("oleacc_test", "test &t &junk", WS_OVERLAPPEDWINDOW,
746             0, 0, 100, 100, NULL, NULL, NULL, NULL);
747     ok(hwnd != NULL, "CreateWindow failed\n");
748     chld = CreateWindowA("static", "message", WS_CHILD | WS_VISIBLE,
749             0, 0, 50, 50, hwnd, NULL, NULL, NULL);
750     ok(chld != NULL, "CreateWindow failed\n");
751 
752     hr = CreateStdAccessibleObject(NULL, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
753     ok(hr == E_FAIL, "got %x\n", hr);
754 
755     hr = CreateStdAccessibleObject(hwnd, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
756     ok(hr == S_OK, "got %x\n", hr);
757 
758     hr = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void**)&ow);
759     ok(hr == S_OK, "got %x\n", hr);
760     hr = IOleWindow_GetWindow(ow, &hwnd2);
761     ok(hr == S_OK, "got %x\n", hr);
762     ok(hwnd == hwnd2, "hwnd2 = %p, expected %p\n", hwnd2, hwnd);
763     hr = WindowFromAccessibleObject(acc, &hwnd2);
764     ok(hr == S_OK, "got %x\n", hr);
765     ok(hwnd == hwnd2, "hwnd2 = %p, expected %p\n", hwnd2, hwnd);
766     IOleWindow_Release(ow);
767 
768     hr = IAccessible_get_accChildCount(acc, &l);
769     ok(hr == S_OK, "got %x\n", hr);
770     ok(l == 1, "l = %d\n", l);
771 
772     V_VT(&vid) = VT_I4;
773     V_I4(&vid) = CHILDID_SELF;
774     disp = (void*)0xdeadbeef;
775     hr = IAccessible_get_accChild(acc, vid, &disp);
776     ok(hr == E_INVALIDARG, "get_accChild returned %x\n", hr);
777     ok(disp == NULL, "disp = %p\n", disp);
778 
779     V_I4(&vid) = 1;
780     disp = (void*)0xdeadbeef;
781     hr = IAccessible_get_accChild(acc, vid, &disp);
782     ok(hr == E_INVALIDARG, "get_accChild returned %x\n", hr);
783     ok(disp == NULL, "disp = %p\n", disp);
784 
785     hr = IAccessible_QueryInterface(acc, &IID_IEnumVARIANT, (void**)&ev);
786     ok(hr == S_OK, "got %x\n", hr);
787 
788     hr = IEnumVARIANT_Skip(ev, 100);
789     ok(hr == S_FALSE, "Skip returned %x\n", hr);
790 
791     V_VT(&v) = VT_I4;
792     fetched = 1;
793     hr = IEnumVARIANT_Next(ev, 1, &v, &fetched);
794     ok(hr == S_FALSE, "got %x\n", hr);
795     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
796     ok(fetched == 0, "fetched = %d\n", fetched);
797 
798     hr = IEnumVARIANT_Reset(ev);
799     ok(hr == S_OK, "got %x\n", hr);
800 
801     V_VT(&v) = VT_I4;
802     fetched = 2;
803     hr = IEnumVARIANT_Next(ev, 1, &v, &fetched);
804     ok(hr == S_OK, "got %x\n", hr);
805     ok(V_VT(&v) == VT_DISPATCH, "V_VT(&v) = %d\n", V_VT(&v));
806     IDispatch_Release(V_DISPATCH(&v));
807     ok(fetched == 1, "fetched = %d\n", fetched);
808     IEnumVARIANT_Release(ev);
809 
810     test_AccessibleChildren(acc);
811 
812     V_VT(&vid) = VT_I4;
813     V_I4(&vid) = CHILDID_SELF;
814     hr = IAccessible_get_accName(acc, vid, &str);
815     ok(hr == S_OK, "got %x\n", hr);
816     ok(!lstrcmpW(str, testW), "name = %s\n", wine_dbgstr_w(str));
817     SysFreeString(str);
818 
819     V_I4(&vid) = 1;
820     str = (void*)0xdeadbeef;
821     hr = IAccessible_get_accName(acc, vid, &str);
822     ok(hr == E_INVALIDARG, "got %x\n", hr);
823     ok(!str, "str != NULL\n");
824     V_I4(&vid) = CHILDID_SELF;
825 
826     str = (void*)0xdeadbeef;
827     hr = IAccessible_get_accValue(acc, vid, &str);
828     ok(hr == S_FALSE, "got %x\n", hr);
829     ok(!str, "str != NULL\n");
830 
831     str = (void*)0xdeadbeef;
832     hr = IAccessible_get_accDescription(acc, vid, &str);
833     ok(hr == S_FALSE, "got %x\n", hr);
834     ok(!str, "str != NULL\n");
835 
836     V_VT(&v) = VT_DISPATCH;
837     V_DISPATCH(&v) = (void*)0xdeadbeef;
838     hr = IAccessible_get_accRole(acc, vid, &v);
839     ok(hr == S_OK, "got %x\n", hr);
840     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
841     ok(V_I4(&v) == ROLE_SYSTEM_CLIENT, "V_I4(&v) = %d\n", V_I4(&v));
842 
843     V_VT(&v) = VT_DISPATCH;
844     V_DISPATCH(&v) = (void*)0xdeadbeef;
845     hr = IAccessible_get_accState(acc, vid, &v);
846     ok(hr == S_OK, "got %x\n", hr);
847     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
848     ok(V_I4(&v) == (STATE_SYSTEM_FOCUSABLE|STATE_SYSTEM_INVISIBLE),
849             "V_I4(&v) = %x\n", V_I4(&v));
850 
851     str = (void*)0xdeadbeef;
852     hr = IAccessible_get_accHelp(acc, vid, &str);
853     ok(hr == S_FALSE, "got %x\n", hr);
854     ok(!str, "str != NULL\n");
855 
856     hr = IAccessible_get_accKeyboardShortcut(acc, vid, &str);
857     ok(hr == S_OK, "got %x\n", hr);
858     ok(!lstrcmpW(str, shortcutW), "str = %s\n", wine_dbgstr_w(str));
859     SysFreeString(str);
860 
861     str = (void*)0xdeadbeef;
862     hr = IAccessible_get_accDefaultAction(acc, vid, &str);
863     ok(hr == S_FALSE, "got %x\n", hr);
864     ok(!str, "str != NULL\n");
865 
866     pt.x = pt.y = 60;
867     ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
868     hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
869     ok(hr == S_OK, "got %x\n", hr);
870     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
871     ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
872 
873     pt.x = pt.y = 25;
874     ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
875     hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
876     ok(hr == S_OK, "got %x\n", hr);
877     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
878     ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
879 
880     ShowWindow(hwnd, TRUE);
881     pt.x = pt.y = 60;
882     ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
883     hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
884     ok(hr == S_OK, "got %x\n", hr);
885     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
886     ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
887 
888     pt.x = pt.y = 25;
889     ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
890     hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
891     ok(hr == S_OK, "got %x\n", hr);
892     ok(V_VT(&v) == VT_DISPATCH, "V_VT(&v) = %d\n", V_VT(&v));
893     ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(&v) = %p\n", V_DISPATCH(&v));
894     VariantClear(&v);
895 
896     ShowWindow(chld, FALSE);
897     pt.x = pt.y = 25;
898     ok(ClientToScreen(hwnd, &pt), "ClientToScreen failed\n");
899     hr = IAccessible_accHitTest(acc, pt.x, pt.y, &v);
900     ok(hr == S_OK, "got %x\n", hr);
901     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
902     ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
903 
904     hr = IAccessible_get_accParent(acc, &disp);
905     ok(hr == S_OK, "got %x\n", hr);
906     ok(disp != NULL, "disp == NULL\n");
907     IDispatch_Release(disp);
908 
909     ok(GetClientRect(hwnd, &rect), "GetClientRect failed\n");
910     pt.x = rect.left;
911     pt.y = rect.top;
912     MapWindowPoints(hwnd, NULL, &pt, 1);
913     rect.left = pt.x;
914     rect.top = pt.y;
915     pt.x = rect.right;
916     pt.y = rect.bottom;
917     MapWindowPoints(hwnd, NULL, &pt, 1);
918     hr = IAccessible_accLocation(acc, &left, &top, &width, &height, vid);
919     ok(hr == S_OK, "got %x\n", hr);
920     ok(left == rect.left, "left = %d, expected %d\n", left, rect.left);
921     ok(top == rect.top, "top = %d, expected %d\n", top, rect.top);
922     ok(width == pt.x-rect.left, "width = %d, expected %d\n", width, pt.x-rect.left);
923     ok(height == pt.y-rect.top, "height = %d, expected %d\n", height, pt.y-rect.top);
924 
925     DestroyWindow(hwnd);
926 
927     hr = IAccessible_get_accChildCount(acc, &l);
928     ok(hr == S_OK, "got %x\n", hr);
929     ok(l == 0, "l = %d\n", l);
930 
931     hr = IAccessible_get_accName(acc, vid, &str);
932     ok(hr == E_INVALIDARG, "got %x\n", hr);
933 
934     hr = IAccessible_get_accValue(acc, vid, &str);
935     ok(hr == S_FALSE, "got %x\n", hr);
936 
937     hr = IAccessible_get_accRole(acc, vid, &v);
938     ok(hr == S_OK, "got %x\n", hr);
939     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
940     ok(V_I4(&v) == ROLE_SYSTEM_CLIENT, "V_I4(&v) = %d\n", V_I4(&v));
941 
942     hr = IAccessible_get_accState(acc, vid, &v);
943     ok(hr == S_OK, "got %x\n", hr);
944     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
945     ok(V_I4(&v) == STATE_SYSTEM_INVISIBLE, "V_I4(&v) = %x\n", V_I4(&v));
946 
947     hr = IAccessible_accHitTest(acc, 200, 200, &v);
948     ok(hr == S_OK, "got %x\n", hr);
949     ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
950     ok(V_I4(&v) == 0, "V_I4(&v) = %d\n", V_I4(&v));
951 
952     disp = (void*)0xdeadbeef;
953     hr = IAccessible_get_accParent(acc, &disp);
954     ok(hr == E_FAIL, "got %x\n", hr);
955     ok(disp == NULL, "disp = %p\n", disp);
956 
957     hr = IAccessible_accLocation(acc, &left, &top, &width, &height, vid);
958     ok(hr == S_OK, "got %x\n", hr);
959     ok(left == 0, "left =  %d\n", left);
960     ok(top == 0, "top =  %d\n", top);
961     ok(width == 0, "width =  %d\n", width);
962     ok(height == 0, "height =  %d\n", height);
963 
964     IAccessible_Release(acc);
965 }
966 
967 static void test_CAccPropServices(void)
968 {
969     IAccPropServices *acc_prop_services;
970     HRESULT hres;
971 
972     hres = CoCreateInstance(&CLSID_CAccPropServices, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
973             &IID_IAccPropServices, (void**)&acc_prop_services);
974     ok(hres == S_OK, "Could not create CAccPropServices instance: %08x\n", hres);
975 
976     IAccPropServices_Release(acc_prop_services);
977 }
978 
979 START_TEST(main)
980 {
981     int argc;
982     char **argv;
983 
984     if(!init())
985         return;
986 
987     CoInitializeEx(NULL, COINIT_MULTITHREADED);
988 
989     argc = winetest_get_mainargs(&argv);
990     if(argc == 4 && !strcmp(argv[2], "ObjectFromLresult")) {
991         IUnknown *unk;
992         HRESULT hres;
993         LRESULT lres;
994 
995         lres = _strtoi64( argv[3], NULL, 16 );
996         hres = ObjectFromLresult(lres, &IID_IUnknown, 0, (void**)&unk);
997         ok(hres == S_OK, "hres = %x\n", hres);
998         IUnknown_Release(unk);
999 
1000         CoUninitialize();
1001         return;
1002     }
1003 
1004     if(!register_window_class()) {
1005         skip("can't register test window class\n");
1006         return;
1007     }
1008 
1009     test_getroletext();
1010     test_GetStateText();
1011     test_LresultFromObject(argv[0]);
1012     test_AccessibleObjectFromWindow();
1013     test_GetProcessHandleFromHwnd();
1014     test_default_client_accessible_object();
1015     test_AccessibleChildren(&Accessible);
1016 
1017     unregister_window_class();
1018     CoUninitialize();
1019 
1020     CoInitialize(NULL);
1021     test_CAccPropServices();
1022     CoUninitialize();
1023 }
1024