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
21 #include "oleacc_private.h"
23 #include "wine/unicode.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(oleacc
);
29 IAccessible IAccessible_iface
;
30 IOleWindow IOleWindow_iface
;
31 IEnumVARIANT IEnumVARIANT_iface
;
39 static inline Client
* impl_from_Client(IAccessible
*iface
)
41 return CONTAINING_RECORD(iface
, Client
, IAccessible_iface
);
44 static HRESULT WINAPI
Client_QueryInterface(IAccessible
*iface
, REFIID riid
, void **ppv
)
46 Client
*This
= impl_from_Client(iface
);
48 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
50 if(IsEqualIID(riid
, &IID_IAccessible
) ||
51 IsEqualIID(riid
, &IID_IDispatch
) ||
52 IsEqualIID(riid
, &IID_IUnknown
)) {
54 }else if(IsEqualIID(riid
, &IID_IOleWindow
)) {
55 *ppv
= &This
->IOleWindow_iface
;
56 }else if(IsEqualIID(riid
, &IID_IEnumVARIANT
)) {
57 *ppv
= &This
->IEnumVARIANT_iface
;
59 WARN("no interface: %s\n", debugstr_guid(riid
));
64 IAccessible_AddRef(iface
);
68 static ULONG WINAPI
Client_AddRef(IAccessible
*iface
)
70 Client
*This
= impl_from_Client(iface
);
71 ULONG ref
= InterlockedIncrement(&This
->ref
);
73 TRACE("(%p) ref = %u\n", This
, ref
);
77 static ULONG WINAPI
Client_Release(IAccessible
*iface
)
79 Client
*This
= impl_from_Client(iface
);
80 ULONG ref
= InterlockedDecrement(&This
->ref
);
82 TRACE("(%p) ref = %u\n", This
, ref
);
89 static HRESULT WINAPI
Client_GetTypeInfoCount(IAccessible
*iface
, UINT
*pctinfo
)
91 Client
*This
= impl_from_Client(iface
);
92 FIXME("(%p)->(%p)\n", This
, pctinfo
);
96 static HRESULT WINAPI
Client_GetTypeInfo(IAccessible
*iface
,
97 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
99 Client
*This
= impl_from_Client(iface
);
100 FIXME("(%p)->(%u %x %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
104 static HRESULT WINAPI
Client_GetIDsOfNames(IAccessible
*iface
, REFIID riid
,
105 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
107 Client
*This
= impl_from_Client(iface
);
108 FIXME("(%p)->(%s %p %u %x %p)\n", This
, debugstr_guid(riid
),
109 rgszNames
, cNames
, lcid
, rgDispId
);
113 static HRESULT WINAPI
Client_Invoke(IAccessible
*iface
, DISPID dispIdMember
,
114 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
115 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
117 Client
*This
= impl_from_Client(iface
);
118 FIXME("(%p)->(%x %s %x %x %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
119 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
123 static HRESULT WINAPI
Client_get_accParent(IAccessible
*iface
, IDispatch
**ppdispParent
)
125 Client
*This
= impl_from_Client(iface
);
127 TRACE("(%p)->(%p)\n", This
, ppdispParent
);
129 return AccessibleObjectFromWindow(This
->hwnd
, OBJID_WINDOW
,
130 &IID_IDispatch
, (void**)ppdispParent
);
133 static HRESULT WINAPI
Client_get_accChildCount(IAccessible
*iface
, LONG
*pcountChildren
)
135 Client
*This
= impl_from_Client(iface
);
138 TRACE("(%p)->(%p)\n", This
, pcountChildren
);
141 for(cur
= GetWindow(This
->hwnd
, GW_CHILD
); cur
; cur
= GetWindow(cur
, GW_HWNDNEXT
))
147 static HRESULT WINAPI
Client_get_accChild(IAccessible
*iface
,
148 VARIANT varChildID
, IDispatch
**ppdispChild
)
150 Client
*This
= impl_from_Client(iface
);
152 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varChildID
), ppdispChild
);
158 static HRESULT WINAPI
Client_get_accName(IAccessible
*iface
, VARIANT varID
, BSTR
*pszName
)
160 Client
*This
= impl_from_Client(iface
);
164 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszName
);
167 if(convert_child_id(&varID
) != CHILDID_SELF
|| !IsWindow(This
->hwnd
))
170 len
= SendMessageW(This
->hwnd
, WM_GETTEXT
, sizeof(name
)/sizeof(WCHAR
), (LPARAM
)name
);
174 for(i
=0; i
<len
; i
++) {
177 memmove(name
+i
, name
+i
+1, (len
-i
)*sizeof(WCHAR
));
182 *pszName
= SysAllocStringLen(name
, len
);
183 return *pszName
? S_OK
: E_OUTOFMEMORY
;
186 static HRESULT WINAPI
Client_get_accValue(IAccessible
*iface
, VARIANT varID
, BSTR
*pszValue
)
188 Client
*This
= impl_from_Client(iface
);
190 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszValue
);
193 if(convert_child_id(&varID
) != CHILDID_SELF
)
198 static HRESULT WINAPI
Client_get_accDescription(IAccessible
*iface
,
199 VARIANT varID
, BSTR
*pszDescription
)
201 Client
*This
= impl_from_Client(iface
);
203 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszDescription
);
205 *pszDescription
= NULL
;
206 if(convert_child_id(&varID
) != CHILDID_SELF
)
211 static HRESULT WINAPI
Client_get_accRole(IAccessible
*iface
, VARIANT varID
, VARIANT
*pvarRole
)
213 Client
*This
= impl_from_Client(iface
);
215 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pvarRole
);
217 if(convert_child_id(&varID
) != CHILDID_SELF
) {
218 V_VT(pvarRole
) = VT_EMPTY
;
222 V_VT(pvarRole
) = VT_I4
;
223 V_I4(pvarRole
) = ROLE_SYSTEM_CLIENT
;
227 static HRESULT WINAPI
Client_get_accState(IAccessible
*iface
, VARIANT varID
, VARIANT
*pvarState
)
229 Client
*This
= impl_from_Client(iface
);
232 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pvarState
);
234 if(convert_child_id(&varID
) != CHILDID_SELF
) {
235 V_VT(pvarState
) = VT_EMPTY
;
239 V_VT(pvarState
) = VT_I4
;
242 style
= GetWindowLongW(This
->hwnd
, GWL_STYLE
);
243 if(style
& WS_DISABLED
)
244 V_I4(pvarState
) |= STATE_SYSTEM_UNAVAILABLE
;
245 else if(IsWindow(This
->hwnd
))
246 V_I4(pvarState
) |= STATE_SYSTEM_FOCUSABLE
;
247 if(GetFocus() == This
->hwnd
)
248 V_I4(pvarState
) |= STATE_SYSTEM_FOCUSED
;
249 if(!(style
& WS_VISIBLE
))
250 V_I4(pvarState
) |= STATE_SYSTEM_INVISIBLE
;
254 static HRESULT WINAPI
Client_get_accHelp(IAccessible
*iface
, VARIANT varID
, BSTR
*pszHelp
)
256 Client
*This
= impl_from_Client(iface
);
258 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszHelp
);
261 if(convert_child_id(&varID
) != CHILDID_SELF
)
266 static HRESULT WINAPI
Client_get_accHelpTopic(IAccessible
*iface
,
267 BSTR
*pszHelpFile
, VARIANT varID
, LONG
*pidTopic
)
269 Client
*This
= impl_from_Client(iface
);
270 FIXME("(%p)->(%p %s %p)\n", This
, pszHelpFile
, debugstr_variant(&varID
), pidTopic
);
274 static HRESULT WINAPI
Client_get_accKeyboardShortcut(IAccessible
*iface
,
275 VARIANT varID
, BSTR
*pszKeyboardShortcut
)
277 static const WCHAR shortcut_fmt
[] = {'A','l','t','+','!',0};
278 Client
*This
= impl_from_Client(iface
);
282 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszKeyboardShortcut
);
284 *pszKeyboardShortcut
= NULL
;
285 if(convert_child_id(&varID
) != CHILDID_SELF
)
288 len
= SendMessageW(This
->hwnd
, WM_GETTEXT
, sizeof(name
)/sizeof(WCHAR
), (LPARAM
)name
);
289 for(i
=0; i
<len
; i
++) {
296 *pszKeyboardShortcut
= SysAllocString(shortcut_fmt
);
297 if(!*pszKeyboardShortcut
)
298 return E_OUTOFMEMORY
;
300 (*pszKeyboardShortcut
)[4] = name
[i
+1];
304 static HRESULT WINAPI
Client_get_accFocus(IAccessible
*iface
, VARIANT
*pvarID
)
306 Client
*This
= impl_from_Client(iface
);
307 FIXME("(%p)->(%p)\n", This
, pvarID
);
311 static HRESULT WINAPI
Client_get_accSelection(IAccessible
*iface
, VARIANT
*pvarID
)
313 Client
*This
= impl_from_Client(iface
);
314 FIXME("(%p)->(%p)\n", This
, pvarID
);
318 static HRESULT WINAPI
Client_get_accDefaultAction(IAccessible
*iface
,
319 VARIANT varID
, BSTR
*pszDefaultAction
)
321 Client
*This
= impl_from_Client(iface
);
323 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszDefaultAction
);
325 *pszDefaultAction
= NULL
;
326 if(convert_child_id(&varID
) != CHILDID_SELF
)
331 static HRESULT WINAPI
Client_accSelect(IAccessible
*iface
, LONG flagsSelect
, VARIANT varID
)
333 Client
*This
= impl_from_Client(iface
);
334 FIXME("(%p)->(%x %s)\n", This
, flagsSelect
, debugstr_variant(&varID
));
338 static HRESULT WINAPI
Client_accLocation(IAccessible
*iface
, LONG
*pxLeft
,
339 LONG
*pyTop
, LONG
*pcxWidth
, LONG
*pcyHeight
, VARIANT varID
)
341 Client
*This
= impl_from_Client(iface
);
345 TRACE("(%p)->(%p %p %p %p %s)\n", This
, pxLeft
, pyTop
,
346 pcxWidth
, pcyHeight
, debugstr_variant(&varID
));
348 *pxLeft
= *pyTop
= *pcxWidth
= *pcyHeight
= 0;
349 if(convert_child_id(&varID
) != CHILDID_SELF
)
352 if(!GetClientRect(This
->hwnd
, &rect
))
357 MapWindowPoints(This
->hwnd
, NULL
, &pt
, 1);
363 MapWindowPoints(This
->hwnd
, NULL
, &pt
, 1);
364 *pcxWidth
= pt
.x
- *pxLeft
;
365 *pcyHeight
= pt
.y
- *pyTop
;
369 static HRESULT WINAPI
Client_accNavigate(IAccessible
*iface
,
370 LONG navDir
, VARIANT varStart
, VARIANT
*pvarEnd
)
372 Client
*This
= impl_from_Client(iface
);
373 FIXME("(%p)->(%d %s %p)\n", This
, navDir
, debugstr_variant(&varStart
), pvarEnd
);
377 static HRESULT WINAPI
Client_accHitTest(IAccessible
*iface
,
378 LONG xLeft
, LONG yTop
, VARIANT
*pvarID
)
380 Client
*This
= impl_from_Client(iface
);
384 TRACE("(%p)->(%d %d %p)\n", This
, xLeft
, yTop
, pvarID
);
386 V_VT(pvarID
) = VT_I4
;
391 if(!IsWindowVisible(This
->hwnd
) || !ScreenToClient(This
->hwnd
, &pt
))
394 child
= ChildWindowFromPointEx(This
->hwnd
, pt
, CWP_SKIPINVISIBLE
);
395 if(!child
|| child
==This
->hwnd
)
398 V_VT(pvarID
) = VT_DISPATCH
;
399 return AccessibleObjectFromWindow(child
, OBJID_WINDOW
,
400 &IID_IDispatch
, (void**)&V_DISPATCH(pvarID
));
403 static HRESULT WINAPI
Client_accDoDefaultAction(IAccessible
*iface
, VARIANT varID
)
405 Client
*This
= impl_from_Client(iface
);
406 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&varID
));
410 static HRESULT WINAPI
Client_put_accName(IAccessible
*iface
, VARIANT varID
, BSTR pszName
)
412 Client
*This
= impl_from_Client(iface
);
413 FIXME("(%p)->(%s %s)\n", This
, debugstr_variant(&varID
), debugstr_w(pszName
));
417 static HRESULT WINAPI
Client_put_accValue(IAccessible
*iface
, VARIANT varID
, BSTR pszValue
)
419 Client
*This
= impl_from_Client(iface
);
420 FIXME("(%p)->(%s %s)\n", This
, debugstr_variant(&varID
), debugstr_w(pszValue
));
424 static const IAccessibleVtbl ClientVtbl
= {
425 Client_QueryInterface
,
428 Client_GetTypeInfoCount
,
430 Client_GetIDsOfNames
,
432 Client_get_accParent
,
433 Client_get_accChildCount
,
437 Client_get_accDescription
,
441 Client_get_accHelpTopic
,
442 Client_get_accKeyboardShortcut
,
444 Client_get_accSelection
,
445 Client_get_accDefaultAction
,
450 Client_accDoDefaultAction
,
455 static inline Client
* impl_from_Client_OleWindow(IOleWindow
*iface
)
457 return CONTAINING_RECORD(iface
, Client
, IOleWindow_iface
);
460 static HRESULT WINAPI
Client_OleWindow_QueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppv
)
462 Client
*This
= impl_from_Client_OleWindow(iface
);
463 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, ppv
);
466 static ULONG WINAPI
Client_OleWindow_AddRef(IOleWindow
*iface
)
468 Client
*This
= impl_from_Client_OleWindow(iface
);
469 return IAccessible_AddRef(&This
->IAccessible_iface
);
472 static ULONG WINAPI
Client_OleWindow_Release(IOleWindow
*iface
)
474 Client
*This
= impl_from_Client_OleWindow(iface
);
475 return IAccessible_Release(&This
->IAccessible_iface
);
478 static HRESULT WINAPI
Client_OleWindow_GetWindow(IOleWindow
*iface
, HWND
*phwnd
)
480 Client
*This
= impl_from_Client_OleWindow(iface
);
482 TRACE("(%p)->(%p)\n", This
, phwnd
);
488 static HRESULT WINAPI
Client_OleWindow_ContextSensitiveHelp(IOleWindow
*iface
, BOOL fEnterMode
)
490 Client
*This
= impl_from_Client_OleWindow(iface
);
491 FIXME("(%p)->(%x)\n", This
, fEnterMode
);
495 static const IOleWindowVtbl ClientOleWindowVtbl
= {
496 Client_OleWindow_QueryInterface
,
497 Client_OleWindow_AddRef
,
498 Client_OleWindow_Release
,
499 Client_OleWindow_GetWindow
,
500 Client_OleWindow_ContextSensitiveHelp
503 static inline Client
* impl_from_Client_EnumVARIANT(IEnumVARIANT
*iface
)
505 return CONTAINING_RECORD(iface
, Client
, IEnumVARIANT_iface
);
508 static HRESULT WINAPI
Client_EnumVARIANT_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **ppv
)
510 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
511 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, ppv
);
514 static ULONG WINAPI
Client_EnumVARIANT_AddRef(IEnumVARIANT
*iface
)
516 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
517 return IAccessible_AddRef(&This
->IAccessible_iface
);
520 static ULONG WINAPI
Client_EnumVARIANT_Release(IEnumVARIANT
*iface
)
522 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
523 return IAccessible_Release(&This
->IAccessible_iface
);
526 static HRESULT WINAPI
Client_EnumVARIANT_Next(IEnumVARIANT
*iface
,
527 ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
529 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
530 HWND cur
= This
->enum_pos
, next
;
534 TRACE("(%p)->(%u %p %p)\n", This
, celt
, rgVar
, pCeltFetched
);
543 next
= GetWindow(This
->hwnd
, GW_CHILD
);
545 next
= GetWindow(This
->enum_pos
, GW_HWNDNEXT
);
550 V_VT(rgVar
+fetched
) = VT_DISPATCH
;
551 hr
= AccessibleObjectFromWindow(cur
, OBJID_WINDOW
,
552 &IID_IDispatch
, (void**)&V_DISPATCH(rgVar
+fetched
));
554 V_VT(rgVar
+fetched
) = VT_EMPTY
;
556 VariantClear(rgVar
+fetched
-1);
567 next
= GetWindow(cur
, GW_HWNDNEXT
);
570 This
->enum_pos
= cur
;
572 *pCeltFetched
= fetched
;
573 return celt
== fetched
? S_OK
: S_FALSE
;
576 static HRESULT WINAPI
Client_EnumVARIANT_Skip(IEnumVARIANT
*iface
, ULONG celt
)
578 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
581 TRACE("(%p)->(%u)\n", This
, celt
);
585 next
= GetWindow(This
->hwnd
, GW_CHILD
);
587 next
= GetWindow(This
->enum_pos
, GW_HWNDNEXT
);
591 This
->enum_pos
= next
;
598 static HRESULT WINAPI
Client_EnumVARIANT_Reset(IEnumVARIANT
*iface
)
600 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
602 TRACE("(%p)\n", This
);
608 static HRESULT WINAPI
Client_EnumVARIANT_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
610 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
611 FIXME("(%p)->(%p)\n", This
, ppEnum
);
615 static const IEnumVARIANTVtbl ClientEnumVARIANTVtbl
= {
616 Client_EnumVARIANT_QueryInterface
,
617 Client_EnumVARIANT_AddRef
,
618 Client_EnumVARIANT_Release
,
619 Client_EnumVARIANT_Next
,
620 Client_EnumVARIANT_Skip
,
621 Client_EnumVARIANT_Reset
,
622 Client_EnumVARIANT_Clone
625 HRESULT
create_client_object(HWND hwnd
, const IID
*iid
, void **obj
)
633 client
= heap_alloc_zero(sizeof(Client
));
635 return E_OUTOFMEMORY
;
637 client
->IAccessible_iface
.lpVtbl
= &ClientVtbl
;
638 client
->IOleWindow_iface
.lpVtbl
= &ClientOleWindowVtbl
;
639 client
->IEnumVARIANT_iface
.lpVtbl
= &ClientEnumVARIANTVtbl
;
642 client
->enum_pos
= 0;
644 hres
= IAccessible_QueryInterface(&client
->IAccessible_iface
, iid
, obj
);
645 IAccessible_Release(&client
->IAccessible_iface
);