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"
25 #include "wine/heap.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(oleacc
);
30 IAccessible IAccessible_iface
;
31 IOleWindow IOleWindow_iface
;
32 IEnumVARIANT IEnumVARIANT_iface
;
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
)) {
55 }else if(IsEqualIID(riid
, &IID_IOleWindow
)) {
56 *ppv
= &This
->IOleWindow_iface
;
57 }else if(IsEqualIID(riid
, &IID_IEnumVARIANT
)) {
58 *ppv
= &This
->IEnumVARIANT_iface
;
60 WARN("no interface: %s\n", debugstr_guid(riid
));
65 IAccessible_AddRef(iface
);
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
);
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
);
90 static HRESULT WINAPI
Client_GetTypeInfoCount(IAccessible
*iface
, UINT
*pctinfo
)
92 Client
*This
= impl_from_Client(iface
);
93 FIXME("(%p)->(%p)\n", This
, pctinfo
);
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
);
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
);
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
);
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
);
139 TRACE("(%p)->(%p)\n", This
, pcountChildren
);
142 for(cur
= GetWindow(This
->hwnd
, GW_CHILD
); cur
; cur
= GetWindow(cur
, GW_HWNDNEXT
))
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
);
159 static HRESULT WINAPI
Client_get_accName(IAccessible
*iface
, VARIANT varID
, BSTR
*pszName
)
161 Client
*This
= impl_from_Client(iface
);
165 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszName
);
168 if(convert_child_id(&varID
) != CHILDID_SELF
|| !IsWindow(This
->hwnd
))
171 len
= SendMessageW(This
->hwnd
, WM_GETTEXT
, sizeof(name
)/sizeof(WCHAR
), (LPARAM
)name
);
175 for(i
=0; i
<len
; i
++) {
178 memmove(name
+i
, name
+i
+1, (len
-i
)*sizeof(WCHAR
));
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
);
194 if(convert_child_id(&varID
) != CHILDID_SELF
)
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
)
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
;
223 V_VT(pvarRole
) = VT_I4
;
224 V_I4(pvarRole
) = ROLE_SYSTEM_CLIENT
;
228 static HRESULT WINAPI
Client_get_accState(IAccessible
*iface
, VARIANT varID
, VARIANT
*pvarState
)
230 Client
*This
= impl_from_Client(iface
);
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
;
240 V_VT(pvarState
) = VT_I4
;
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
;
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
);
262 if(convert_child_id(&varID
) != CHILDID_SELF
)
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
);
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
);
283 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszKeyboardShortcut
);
285 *pszKeyboardShortcut
= NULL
;
286 if(convert_child_id(&varID
) != CHILDID_SELF
)
289 len
= SendMessageW(This
->hwnd
, WM_GETTEXT
, sizeof(name
)/sizeof(WCHAR
), (LPARAM
)name
);
290 for(i
=0; i
<len
; i
++) {
297 *pszKeyboardShortcut
= SysAllocString(shortcut_fmt
);
298 if(!*pszKeyboardShortcut
)
299 return E_OUTOFMEMORY
;
301 (*pszKeyboardShortcut
)[4] = name
[i
+1];
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
);
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
);
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
)
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
));
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
);
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
)
353 if(!GetClientRect(This
->hwnd
, &rect
))
358 MapWindowPoints(This
->hwnd
, NULL
, &pt
, 1);
364 MapWindowPoints(This
->hwnd
, NULL
, &pt
, 1);
365 *pcxWidth
= pt
.x
- *pxLeft
;
366 *pcyHeight
= pt
.y
- *pyTop
;
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
);
378 static HRESULT WINAPI
Client_accHitTest(IAccessible
*iface
,
379 LONG xLeft
, LONG yTop
, VARIANT
*pvarID
)
381 Client
*This
= impl_from_Client(iface
);
385 TRACE("(%p)->(%d %d %p)\n", This
, xLeft
, yTop
, pvarID
);
387 V_VT(pvarID
) = VT_I4
;
392 if(!IsWindowVisible(This
->hwnd
) || !ScreenToClient(This
->hwnd
, &pt
))
395 child
= ChildWindowFromPointEx(This
->hwnd
, pt
, CWP_SKIPINVISIBLE
);
396 if(!child
|| child
==This
->hwnd
)
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
));
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
));
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
));
425 static const IAccessibleVtbl ClientVtbl
= {
426 Client_QueryInterface
,
429 Client_GetTypeInfoCount
,
431 Client_GetIDsOfNames
,
433 Client_get_accParent
,
434 Client_get_accChildCount
,
438 Client_get_accDescription
,
442 Client_get_accHelpTopic
,
443 Client_get_accKeyboardShortcut
,
445 Client_get_accSelection
,
446 Client_get_accDefaultAction
,
451 Client_accDoDefaultAction
,
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
);
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
);
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
;
535 TRACE("(%p)->(%u %p %p)\n", This
, celt
, rgVar
, pCeltFetched
);
544 next
= GetWindow(This
->hwnd
, GW_CHILD
);
546 next
= GetWindow(This
->enum_pos
, GW_HWNDNEXT
);
551 V_VT(rgVar
+fetched
) = VT_DISPATCH
;
552 hr
= AccessibleObjectFromWindow(cur
, OBJID_WINDOW
,
553 &IID_IDispatch
, (void**)&V_DISPATCH(rgVar
+fetched
));
555 V_VT(rgVar
+fetched
) = VT_EMPTY
;
557 VariantClear(rgVar
+fetched
-1);
568 next
= GetWindow(cur
, GW_HWNDNEXT
);
571 This
->enum_pos
= cur
;
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
);
582 TRACE("(%p)->(%u)\n", This
, celt
);
586 next
= GetWindow(This
->hwnd
, GW_CHILD
);
588 next
= GetWindow(This
->enum_pos
, GW_HWNDNEXT
);
592 This
->enum_pos
= next
;
599 static HRESULT WINAPI
Client_EnumVARIANT_Reset(IEnumVARIANT
*iface
)
601 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
603 TRACE("(%p)\n", This
);
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
);
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
)
634 client
= heap_alloc_zero(sizeof(Client
));
636 return E_OUTOFMEMORY
;
638 client
->IAccessible_iface
.lpVtbl
= &ClientVtbl
;
639 client
->IOleWindow_iface
.lpVtbl
= &ClientOleWindowVtbl
;
640 client
->IEnumVARIANT_iface
.lpVtbl
= &ClientEnumVARIANTVtbl
;
643 client
->enum_pos
= 0;
645 hres
= IAccessible_QueryInterface(&client
->IAccessible_iface
, iid
, obj
);
646 IAccessible_Release(&client
->IAccessible_iface
);