user32/tests: Reorganize the DPI tests.
[wine.git] / dlls / oleacc / client.c
blob5b1f0eee5fb3b999bb76899bacf4cac37755a608
1 /*
2 * Copyright 2014 Piotr Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "oleacc_private.h"
23 #include "wine/unicode.h"
24 #include "wine/debug.h"
25 #include "wine/heap.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
29 typedef struct {
30 IAccessible IAccessible_iface;
31 IOleWindow IOleWindow_iface;
32 IEnumVARIANT IEnumVARIANT_iface;
34 LONG ref;
36 HWND hwnd;
37 HWND enum_pos;
38 } Client;
40 static inline Client* impl_from_Client(IAccessible *iface)
42 return CONTAINING_RECORD(iface, Client, IAccessible_iface);
45 static HRESULT WINAPI Client_QueryInterface(IAccessible *iface, REFIID riid, void **ppv)
47 Client *This = impl_from_Client(iface);
49 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
51 if(IsEqualIID(riid, &IID_IAccessible) ||
52 IsEqualIID(riid, &IID_IDispatch) ||
53 IsEqualIID(riid, &IID_IUnknown)) {
54 *ppv = iface;
55 }else if(IsEqualIID(riid, &IID_IOleWindow)) {
56 *ppv = &This->IOleWindow_iface;
57 }else if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
58 *ppv = &This->IEnumVARIANT_iface;
59 }else {
60 WARN("no interface: %s\n", debugstr_guid(riid));
61 *ppv = NULL;
62 return E_NOINTERFACE;
65 IAccessible_AddRef(iface);
66 return S_OK;
69 static ULONG WINAPI Client_AddRef(IAccessible *iface)
71 Client *This = impl_from_Client(iface);
72 ULONG ref = InterlockedIncrement(&This->ref);
74 TRACE("(%p) ref = %u\n", This, ref);
75 return ref;
78 static ULONG WINAPI Client_Release(IAccessible *iface)
80 Client *This = impl_from_Client(iface);
81 ULONG ref = InterlockedDecrement(&This->ref);
83 TRACE("(%p) ref = %u\n", This, ref);
85 if(!ref)
86 heap_free(This);
87 return ref;
90 static HRESULT WINAPI Client_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
92 Client *This = impl_from_Client(iface);
93 FIXME("(%p)->(%p)\n", This, pctinfo);
94 return E_NOTIMPL;
97 static HRESULT WINAPI Client_GetTypeInfo(IAccessible *iface,
98 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
100 Client *This = impl_from_Client(iface);
101 FIXME("(%p)->(%u %x %p)\n", This, iTInfo, lcid, ppTInfo);
102 return E_NOTIMPL;
105 static HRESULT WINAPI Client_GetIDsOfNames(IAccessible *iface, REFIID riid,
106 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
108 Client *This = impl_from_Client(iface);
109 FIXME("(%p)->(%s %p %u %x %p)\n", This, debugstr_guid(riid),
110 rgszNames, cNames, lcid, rgDispId);
111 return E_NOTIMPL;
114 static HRESULT WINAPI Client_Invoke(IAccessible *iface, DISPID dispIdMember,
115 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
116 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
118 Client *This = impl_from_Client(iface);
119 FIXME("(%p)->(%x %s %x %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
120 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
121 return E_NOTIMPL;
124 static HRESULT WINAPI Client_get_accParent(IAccessible *iface, IDispatch **ppdispParent)
126 Client *This = impl_from_Client(iface);
128 TRACE("(%p)->(%p)\n", This, ppdispParent);
130 return AccessibleObjectFromWindow(This->hwnd, OBJID_WINDOW,
131 &IID_IDispatch, (void**)ppdispParent);
134 static HRESULT WINAPI Client_get_accChildCount(IAccessible *iface, LONG *pcountChildren)
136 Client *This = impl_from_Client(iface);
137 HWND cur;
139 TRACE("(%p)->(%p)\n", This, pcountChildren);
141 *pcountChildren = 0;
142 for(cur = GetWindow(This->hwnd, GW_CHILD); cur; cur = GetWindow(cur, GW_HWNDNEXT))
143 (*pcountChildren)++;
145 return S_OK;
148 static HRESULT WINAPI Client_get_accChild(IAccessible *iface,
149 VARIANT varChildID, IDispatch **ppdispChild)
151 Client *This = impl_from_Client(iface);
153 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varChildID), ppdispChild);
155 *ppdispChild = NULL;
156 return E_INVALIDARG;
159 static HRESULT WINAPI Client_get_accName(IAccessible *iface, VARIANT varID, BSTR *pszName)
161 Client *This = impl_from_Client(iface);
162 WCHAR name[1024];
163 UINT i, len;
165 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszName);
167 *pszName = NULL;
168 if(convert_child_id(&varID) != CHILDID_SELF || !IsWindow(This->hwnd))
169 return E_INVALIDARG;
171 len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name);
172 if(!len)
173 return S_FALSE;
175 for(i=0; i<len; i++) {
176 if(name[i] == '&') {
177 len--;
178 memmove(name+i, name+i+1, (len-i)*sizeof(WCHAR));
179 break;
183 *pszName = SysAllocStringLen(name, len);
184 return *pszName ? S_OK : E_OUTOFMEMORY;
187 static HRESULT WINAPI Client_get_accValue(IAccessible *iface, VARIANT varID, BSTR *pszValue)
189 Client *This = impl_from_Client(iface);
191 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszValue);
193 *pszValue = NULL;
194 if(convert_child_id(&varID) != CHILDID_SELF)
195 return E_INVALIDARG;
196 return S_FALSE;
199 static HRESULT WINAPI Client_get_accDescription(IAccessible *iface,
200 VARIANT varID, BSTR *pszDescription)
202 Client *This = impl_from_Client(iface);
204 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDescription);
206 *pszDescription = NULL;
207 if(convert_child_id(&varID) != CHILDID_SELF)
208 return E_INVALIDARG;
209 return S_FALSE;
212 static HRESULT WINAPI Client_get_accRole(IAccessible *iface, VARIANT varID, VARIANT *pvarRole)
214 Client *This = impl_from_Client(iface);
216 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarRole);
218 if(convert_child_id(&varID) != CHILDID_SELF) {
219 V_VT(pvarRole) = VT_EMPTY;
220 return E_INVALIDARG;
223 V_VT(pvarRole) = VT_I4;
224 V_I4(pvarRole) = ROLE_SYSTEM_CLIENT;
225 return S_OK;
228 static HRESULT WINAPI Client_get_accState(IAccessible *iface, VARIANT varID, VARIANT *pvarState)
230 Client *This = impl_from_Client(iface);
231 LONG style;
233 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarState);
235 if(convert_child_id(&varID) != CHILDID_SELF) {
236 V_VT(pvarState) = VT_EMPTY;
237 return E_INVALIDARG;
240 V_VT(pvarState) = VT_I4;
241 V_I4(pvarState) = 0;
243 style = GetWindowLongW(This->hwnd, GWL_STYLE);
244 if(style & WS_DISABLED)
245 V_I4(pvarState) |= STATE_SYSTEM_UNAVAILABLE;
246 else if(IsWindow(This->hwnd))
247 V_I4(pvarState) |= STATE_SYSTEM_FOCUSABLE;
248 if(GetFocus() == This->hwnd)
249 V_I4(pvarState) |= STATE_SYSTEM_FOCUSED;
250 if(!(style & WS_VISIBLE))
251 V_I4(pvarState) |= STATE_SYSTEM_INVISIBLE;
252 return S_OK;
255 static HRESULT WINAPI Client_get_accHelp(IAccessible *iface, VARIANT varID, BSTR *pszHelp)
257 Client *This = impl_from_Client(iface);
259 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszHelp);
261 *pszHelp = NULL;
262 if(convert_child_id(&varID) != CHILDID_SELF)
263 return E_INVALIDARG;
264 return S_FALSE;
267 static HRESULT WINAPI Client_get_accHelpTopic(IAccessible *iface,
268 BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic)
270 Client *This = impl_from_Client(iface);
271 FIXME("(%p)->(%p %s %p)\n", This, pszHelpFile, debugstr_variant(&varID), pidTopic);
272 return E_NOTIMPL;
275 static HRESULT WINAPI Client_get_accKeyboardShortcut(IAccessible *iface,
276 VARIANT varID, BSTR *pszKeyboardShortcut)
278 static const WCHAR shortcut_fmt[] = {'A','l','t','+','!',0};
279 Client *This = impl_from_Client(iface);
280 WCHAR name[1024];
281 UINT i, len;
283 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszKeyboardShortcut);
285 *pszKeyboardShortcut = NULL;
286 if(convert_child_id(&varID) != CHILDID_SELF)
287 return E_INVALIDARG;
289 len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name);
290 for(i=0; i<len; i++) {
291 if(name[i] == '&')
292 break;
294 if(i+1 >= len)
295 return S_FALSE;
297 *pszKeyboardShortcut = SysAllocString(shortcut_fmt);
298 if(!*pszKeyboardShortcut)
299 return E_OUTOFMEMORY;
301 (*pszKeyboardShortcut)[4] = name[i+1];
302 return S_OK;
305 static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *pvarID)
307 Client *This = impl_from_Client(iface);
308 FIXME("(%p)->(%p)\n", This, pvarID);
309 return E_NOTIMPL;
312 static HRESULT WINAPI Client_get_accSelection(IAccessible *iface, VARIANT *pvarID)
314 Client *This = impl_from_Client(iface);
315 FIXME("(%p)->(%p)\n", This, pvarID);
316 return E_NOTIMPL;
319 static HRESULT WINAPI Client_get_accDefaultAction(IAccessible *iface,
320 VARIANT varID, BSTR *pszDefaultAction)
322 Client *This = impl_from_Client(iface);
324 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDefaultAction);
326 *pszDefaultAction = NULL;
327 if(convert_child_id(&varID) != CHILDID_SELF)
328 return E_INVALIDARG;
329 return S_FALSE;
332 static HRESULT WINAPI Client_accSelect(IAccessible *iface, LONG flagsSelect, VARIANT varID)
334 Client *This = impl_from_Client(iface);
335 FIXME("(%p)->(%x %s)\n", This, flagsSelect, debugstr_variant(&varID));
336 return E_NOTIMPL;
339 static HRESULT WINAPI Client_accLocation(IAccessible *iface, LONG *pxLeft,
340 LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID)
342 Client *This = impl_from_Client(iface);
343 RECT rect;
344 POINT pt;
346 TRACE("(%p)->(%p %p %p %p %s)\n", This, pxLeft, pyTop,
347 pcxWidth, pcyHeight, debugstr_variant(&varID));
349 *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
350 if(convert_child_id(&varID) != CHILDID_SELF)
351 return E_INVALIDARG;
353 if(!GetClientRect(This->hwnd, &rect))
354 return S_OK;
356 pt.x = rect.left,
357 pt.y = rect.top;
358 MapWindowPoints(This->hwnd, NULL, &pt, 1);
359 *pxLeft = pt.x;
360 *pyTop = pt.y;
362 pt.x = rect.right;
363 pt.y = rect.bottom;
364 MapWindowPoints(This->hwnd, NULL, &pt, 1);
365 *pcxWidth = pt.x - *pxLeft;
366 *pcyHeight = pt.y - *pyTop;
367 return S_OK;
370 static HRESULT WINAPI Client_accNavigate(IAccessible *iface,
371 LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
373 Client *This = impl_from_Client(iface);
374 FIXME("(%p)->(%d %s %p)\n", This, navDir, debugstr_variant(&varStart), pvarEnd);
375 return E_NOTIMPL;
378 static HRESULT WINAPI Client_accHitTest(IAccessible *iface,
379 LONG xLeft, LONG yTop, VARIANT *pvarID)
381 Client *This = impl_from_Client(iface);
382 HWND child;
383 POINT pt;
385 TRACE("(%p)->(%d %d %p)\n", This, xLeft, yTop, pvarID);
387 V_VT(pvarID) = VT_I4;
388 V_I4(pvarID) = 0;
390 pt.x = xLeft;
391 pt.y = yTop;
392 if(!IsWindowVisible(This->hwnd) || !ScreenToClient(This->hwnd, &pt))
393 return S_OK;
395 child = ChildWindowFromPointEx(This->hwnd, pt, CWP_SKIPINVISIBLE);
396 if(!child || child==This->hwnd)
397 return S_OK;
399 V_VT(pvarID) = VT_DISPATCH;
400 return AccessibleObjectFromWindow(child, OBJID_WINDOW,
401 &IID_IDispatch, (void**)&V_DISPATCH(pvarID));
404 static HRESULT WINAPI Client_accDoDefaultAction(IAccessible *iface, VARIANT varID)
406 Client *This = impl_from_Client(iface);
407 FIXME("(%p)->(%s)\n", This, debugstr_variant(&varID));
408 return E_NOTIMPL;
411 static HRESULT WINAPI Client_put_accName(IAccessible *iface, VARIANT varID, BSTR pszName)
413 Client *This = impl_from_Client(iface);
414 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszName));
415 return E_NOTIMPL;
418 static HRESULT WINAPI Client_put_accValue(IAccessible *iface, VARIANT varID, BSTR pszValue)
420 Client *This = impl_from_Client(iface);
421 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszValue));
422 return E_NOTIMPL;
425 static const IAccessibleVtbl ClientVtbl = {
426 Client_QueryInterface,
427 Client_AddRef,
428 Client_Release,
429 Client_GetTypeInfoCount,
430 Client_GetTypeInfo,
431 Client_GetIDsOfNames,
432 Client_Invoke,
433 Client_get_accParent,
434 Client_get_accChildCount,
435 Client_get_accChild,
436 Client_get_accName,
437 Client_get_accValue,
438 Client_get_accDescription,
439 Client_get_accRole,
440 Client_get_accState,
441 Client_get_accHelp,
442 Client_get_accHelpTopic,
443 Client_get_accKeyboardShortcut,
444 Client_get_accFocus,
445 Client_get_accSelection,
446 Client_get_accDefaultAction,
447 Client_accSelect,
448 Client_accLocation,
449 Client_accNavigate,
450 Client_accHitTest,
451 Client_accDoDefaultAction,
452 Client_put_accName,
453 Client_put_accValue
456 static inline Client* impl_from_Client_OleWindow(IOleWindow *iface)
458 return CONTAINING_RECORD(iface, Client, IOleWindow_iface);
461 static HRESULT WINAPI Client_OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **ppv)
463 Client *This = impl_from_Client_OleWindow(iface);
464 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
467 static ULONG WINAPI Client_OleWindow_AddRef(IOleWindow *iface)
469 Client *This = impl_from_Client_OleWindow(iface);
470 return IAccessible_AddRef(&This->IAccessible_iface);
473 static ULONG WINAPI Client_OleWindow_Release(IOleWindow *iface)
475 Client *This = impl_from_Client_OleWindow(iface);
476 return IAccessible_Release(&This->IAccessible_iface);
479 static HRESULT WINAPI Client_OleWindow_GetWindow(IOleWindow *iface, HWND *phwnd)
481 Client *This = impl_from_Client_OleWindow(iface);
483 TRACE("(%p)->(%p)\n", This, phwnd);
485 *phwnd = This->hwnd;
486 return S_OK;
489 static HRESULT WINAPI Client_OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMode)
491 Client *This = impl_from_Client_OleWindow(iface);
492 FIXME("(%p)->(%x)\n", This, fEnterMode);
493 return E_NOTIMPL;
496 static const IOleWindowVtbl ClientOleWindowVtbl = {
497 Client_OleWindow_QueryInterface,
498 Client_OleWindow_AddRef,
499 Client_OleWindow_Release,
500 Client_OleWindow_GetWindow,
501 Client_OleWindow_ContextSensitiveHelp
504 static inline Client* impl_from_Client_EnumVARIANT(IEnumVARIANT *iface)
506 return CONTAINING_RECORD(iface, Client, IEnumVARIANT_iface);
509 static HRESULT WINAPI Client_EnumVARIANT_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
511 Client *This = impl_from_Client_EnumVARIANT(iface);
512 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
515 static ULONG WINAPI Client_EnumVARIANT_AddRef(IEnumVARIANT *iface)
517 Client *This = impl_from_Client_EnumVARIANT(iface);
518 return IAccessible_AddRef(&This->IAccessible_iface);
521 static ULONG WINAPI Client_EnumVARIANT_Release(IEnumVARIANT *iface)
523 Client *This = impl_from_Client_EnumVARIANT(iface);
524 return IAccessible_Release(&This->IAccessible_iface);
527 static HRESULT WINAPI Client_EnumVARIANT_Next(IEnumVARIANT *iface,
528 ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
530 Client *This = impl_from_Client_EnumVARIANT(iface);
531 HWND cur = This->enum_pos, next;
532 ULONG fetched = 0;
533 HRESULT hr;
535 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
537 if(!celt) {
538 if(pCeltFetched)
539 *pCeltFetched = 0;
540 return S_OK;
543 if(!This->enum_pos)
544 next = GetWindow(This->hwnd, GW_CHILD);
545 else
546 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
548 while(next) {
549 cur = next;
551 V_VT(rgVar+fetched) = VT_DISPATCH;
552 hr = AccessibleObjectFromWindow(cur, OBJID_WINDOW,
553 &IID_IDispatch, (void**)&V_DISPATCH(rgVar+fetched));
554 if(FAILED(hr)) {
555 V_VT(rgVar+fetched) = VT_EMPTY;
556 while(fetched > 0) {
557 VariantClear(rgVar+fetched-1);
558 fetched--;
560 if(pCeltFetched)
561 *pCeltFetched = 0;
562 return hr;
564 fetched++;
565 if(fetched == celt)
566 break;
568 next = GetWindow(cur, GW_HWNDNEXT);
571 This->enum_pos = cur;
572 if(pCeltFetched)
573 *pCeltFetched = fetched;
574 return celt == fetched ? S_OK : S_FALSE;
577 static HRESULT WINAPI Client_EnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt)
579 Client *This = impl_from_Client_EnumVARIANT(iface);
580 HWND next;
582 TRACE("(%p)->(%u)\n", This, celt);
584 while(celt) {
585 if(!This->enum_pos)
586 next = GetWindow(This->hwnd, GW_CHILD);
587 else
588 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
589 if(!next)
590 return S_FALSE;
592 This->enum_pos = next;
593 celt--;
596 return S_OK;
599 static HRESULT WINAPI Client_EnumVARIANT_Reset(IEnumVARIANT *iface)
601 Client *This = impl_from_Client_EnumVARIANT(iface);
603 TRACE("(%p)\n", This);
605 This->enum_pos = 0;
606 return S_OK;
609 static HRESULT WINAPI Client_EnumVARIANT_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
611 Client *This = impl_from_Client_EnumVARIANT(iface);
612 FIXME("(%p)->(%p)\n", This, ppEnum);
613 return E_NOTIMPL;
616 static const IEnumVARIANTVtbl ClientEnumVARIANTVtbl = {
617 Client_EnumVARIANT_QueryInterface,
618 Client_EnumVARIANT_AddRef,
619 Client_EnumVARIANT_Release,
620 Client_EnumVARIANT_Next,
621 Client_EnumVARIANT_Skip,
622 Client_EnumVARIANT_Reset,
623 Client_EnumVARIANT_Clone
626 HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj)
628 Client *client;
629 HRESULT hres;
631 if(!IsWindow(hwnd))
632 return E_FAIL;
634 client = heap_alloc_zero(sizeof(Client));
635 if(!client)
636 return E_OUTOFMEMORY;
638 client->IAccessible_iface.lpVtbl = &ClientVtbl;
639 client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl;
640 client->IEnumVARIANT_iface.lpVtbl = &ClientEnumVARIANTVtbl;
641 client->ref = 1;
642 client->hwnd = hwnd;
643 client->enum_pos = 0;
645 hres = IAccessible_QueryInterface(&client->IAccessible_iface, iid, obj);
646 IAccessible_Release(&client->IAccessible_iface);
647 return hres;