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
22 #include "oleacc_private.h"
25 #include "wine/debug.h"
26 #include "wine/heap.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(oleacc
);
30 typedef struct win_class_vtbl win_class_vtbl
;
32 IAccessible IAccessible_iface
;
33 IOleWindow IOleWindow_iface
;
34 IEnumVARIANT IEnumVARIANT_iface
;
35 IServiceProvider IServiceProvider_iface
;
43 const win_class_vtbl
*vtbl
;
46 struct win_class_vtbl
{
47 void (*init
)(Client
*);
48 HRESULT (*get_state
)(Client
*, VARIANT
, VARIANT
*);
49 HRESULT (*get_name
)(Client
*, VARIANT
, BSTR
*);
50 HRESULT (*get_kbd_shortcut
)(Client
*, VARIANT
, BSTR
*);
51 HRESULT (*get_value
)(Client
*, VARIANT
, BSTR
*);
52 HRESULT (*put_value
)(Client
*, VARIANT
, BSTR
);
55 static HRESULT
win_get_name(HWND hwnd
, BSTR
*name
)
60 len
= SendMessageW(hwnd
, WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
64 for(i
=0; i
<len
; i
++) {
67 memmove(buf
+i
, buf
+i
+1, (len
-i
)*sizeof(WCHAR
));
72 *name
= SysAllocStringLen(buf
, len
);
73 return *name
? S_OK
: E_OUTOFMEMORY
;
76 static HRESULT
win_get_kbd_shortcut(HWND hwnd
, BSTR
*shortcut
)
81 len
= SendMessageW(hwnd
, WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
85 for(i
=0; i
<len
; i
++) {
92 *shortcut
= SysAllocString(L
"Alt+!");
95 (*shortcut
)[4] = buf
[i
+1];
99 static inline Client
* impl_from_Client(IAccessible
*iface
)
101 return CONTAINING_RECORD(iface
, Client
, IAccessible_iface
);
104 static HRESULT WINAPI
Client_QueryInterface(IAccessible
*iface
, REFIID riid
, void **ppv
)
106 Client
*This
= impl_from_Client(iface
);
108 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
110 if(IsEqualIID(riid
, &IID_IAccessible
) ||
111 IsEqualIID(riid
, &IID_IDispatch
) ||
112 IsEqualIID(riid
, &IID_IUnknown
)) {
114 }else if(IsEqualIID(riid
, &IID_IOleWindow
)) {
115 *ppv
= &This
->IOleWindow_iface
;
116 }else if(IsEqualIID(riid
, &IID_IEnumVARIANT
)) {
117 *ppv
= &This
->IEnumVARIANT_iface
;
118 }else if(IsEqualIID(riid
, &IID_IServiceProvider
)) {
119 *ppv
= &This
->IServiceProvider_iface
;
121 WARN("no interface: %s\n", debugstr_guid(riid
));
123 return E_NOINTERFACE
;
126 IAccessible_AddRef(iface
);
130 static ULONG WINAPI
Client_AddRef(IAccessible
*iface
)
132 Client
*This
= impl_from_Client(iface
);
133 ULONG ref
= InterlockedIncrement(&This
->ref
);
135 TRACE("(%p) ref = %lu\n", This
, ref
);
139 static ULONG WINAPI
Client_Release(IAccessible
*iface
)
141 Client
*This
= impl_from_Client(iface
);
142 ULONG ref
= InterlockedDecrement(&This
->ref
);
144 TRACE("(%p) ref = %lu\n", This
, ref
);
151 static HRESULT WINAPI
Client_GetTypeInfoCount(IAccessible
*iface
, UINT
*pctinfo
)
153 Client
*This
= impl_from_Client(iface
);
154 FIXME("(%p)->(%p)\n", This
, pctinfo
);
158 static HRESULT WINAPI
Client_GetTypeInfo(IAccessible
*iface
,
159 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
161 Client
*This
= impl_from_Client(iface
);
162 FIXME("(%p)->(%u %lx %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
166 static HRESULT WINAPI
Client_GetIDsOfNames(IAccessible
*iface
, REFIID riid
,
167 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
169 Client
*This
= impl_from_Client(iface
);
170 FIXME("(%p)->(%s %p %u %lx %p)\n", This
, debugstr_guid(riid
),
171 rgszNames
, cNames
, lcid
, rgDispId
);
175 static HRESULT WINAPI
Client_Invoke(IAccessible
*iface
, DISPID dispIdMember
,
176 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
177 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
179 Client
*This
= impl_from_Client(iface
);
180 FIXME("(%p)->(%lx %s %lx %x %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
181 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
185 static HRESULT WINAPI
Client_get_accParent(IAccessible
*iface
, IDispatch
**ppdispParent
)
187 Client
*This
= impl_from_Client(iface
);
189 TRACE("(%p)->(%p)\n", This
, ppdispParent
);
191 return AccessibleObjectFromWindow(This
->hwnd
, OBJID_WINDOW
,
192 &IID_IDispatch
, (void**)ppdispParent
);
195 static HRESULT WINAPI
Client_get_accChildCount(IAccessible
*iface
, LONG
*pcountChildren
)
197 Client
*This
= impl_from_Client(iface
);
200 TRACE("(%p)->(%p)\n", This
, pcountChildren
);
203 for(cur
= GetWindow(This
->hwnd
, GW_CHILD
); cur
; cur
= GetWindow(cur
, GW_HWNDNEXT
))
209 static HRESULT WINAPI
Client_get_accChild(IAccessible
*iface
,
210 VARIANT varChildID
, IDispatch
**ppdispChild
)
212 Client
*This
= impl_from_Client(iface
);
214 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varChildID
), ppdispChild
);
220 static HRESULT WINAPI
Client_get_accName(IAccessible
*iface
, VARIANT id
, BSTR
*name
)
222 Client
*This
= impl_from_Client(iface
);
224 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&id
), name
);
227 if(This
->vtbl
&& This
->vtbl
->get_name
)
228 return This
->vtbl
->get_name(This
, id
, name
);
230 if(convert_child_id(&id
) != CHILDID_SELF
|| !IsWindow(This
->hwnd
))
233 return win_get_name(This
->hwnd
, name
);
236 static HRESULT WINAPI
Client_get_accValue(IAccessible
*iface
, VARIANT id
, BSTR
*value
)
238 Client
*This
= impl_from_Client(iface
);
240 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&id
), value
);
243 if(This
->vtbl
&& This
->vtbl
->get_value
)
244 return This
->vtbl
->get_value(This
, id
, value
);
246 if(convert_child_id(&id
) != CHILDID_SELF
)
251 static HRESULT WINAPI
Client_get_accDescription(IAccessible
*iface
,
252 VARIANT varID
, BSTR
*pszDescription
)
254 Client
*This
= impl_from_Client(iface
);
256 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszDescription
);
258 *pszDescription
= NULL
;
259 if(convert_child_id(&varID
) != CHILDID_SELF
)
264 static HRESULT WINAPI
Client_get_accRole(IAccessible
*iface
, VARIANT varID
, VARIANT
*pvarRole
)
266 Client
*This
= impl_from_Client(iface
);
268 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pvarRole
);
270 if(convert_child_id(&varID
) != CHILDID_SELF
) {
271 V_VT(pvarRole
) = VT_EMPTY
;
275 V_VT(pvarRole
) = VT_I4
;
276 V_I4(pvarRole
) = This
->role
;
280 static HRESULT
client_get_state(Client
*client
, VARIANT id
, VARIANT
*state
)
285 if(convert_child_id(&id
) != CHILDID_SELF
) {
286 V_VT(state
) = VT_EMPTY
;
293 style
= GetWindowLongW(client
->hwnd
, GWL_STYLE
);
294 if(style
& WS_DISABLED
)
295 V_I4(state
) |= STATE_SYSTEM_UNAVAILABLE
;
296 else if(IsWindow(client
->hwnd
))
297 V_I4(state
) |= STATE_SYSTEM_FOCUSABLE
;
299 info
.cbSize
= sizeof(info
);
300 if(GetGUIThreadInfo(0, &info
) && info
.hwndFocus
== client
->hwnd
)
301 V_I4(state
) |= STATE_SYSTEM_FOCUSED
;
302 if(!(style
& WS_VISIBLE
))
303 V_I4(state
) |= STATE_SYSTEM_INVISIBLE
;
307 static HRESULT WINAPI
Client_get_accState(IAccessible
*iface
, VARIANT id
, VARIANT
*state
)
309 Client
*This
= impl_from_Client(iface
);
311 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&id
), state
);
313 if(This
->vtbl
&& This
->vtbl
->get_state
)
314 return This
->vtbl
->get_state(This
, id
, state
);
315 return client_get_state(This
, id
, state
);
318 static HRESULT WINAPI
Client_get_accHelp(IAccessible
*iface
, VARIANT varID
, BSTR
*pszHelp
)
320 Client
*This
= impl_from_Client(iface
);
322 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszHelp
);
325 if(convert_child_id(&varID
) != CHILDID_SELF
)
330 static HRESULT WINAPI
Client_get_accHelpTopic(IAccessible
*iface
,
331 BSTR
*pszHelpFile
, VARIANT varID
, LONG
*pidTopic
)
333 Client
*This
= impl_from_Client(iface
);
334 FIXME("(%p)->(%p %s %p)\n", This
, pszHelpFile
, debugstr_variant(&varID
), pidTopic
);
338 static HRESULT WINAPI
Client_get_accKeyboardShortcut(IAccessible
*iface
,
339 VARIANT id
, BSTR
*shortcut
)
341 Client
*This
= impl_from_Client(iface
);
343 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&id
), shortcut
);
346 if(This
->vtbl
&& This
->vtbl
->get_kbd_shortcut
)
347 return This
->vtbl
->get_kbd_shortcut(This
, id
, shortcut
);
349 if(convert_child_id(&id
) != CHILDID_SELF
)
352 return win_get_kbd_shortcut(This
->hwnd
, shortcut
);
355 static HRESULT WINAPI
Client_get_accFocus(IAccessible
*iface
, VARIANT
*focus
)
357 Client
*This
= impl_from_Client(iface
);
360 TRACE("(%p)->(%p)\n", This
, focus
);
362 V_VT(focus
) = VT_EMPTY
;
363 info
.cbSize
= sizeof(info
);
364 if(GetGUIThreadInfo(0, &info
) && info
.hwndFocus
) {
365 if(info
.hwndFocus
== This
->hwnd
) {
367 V_I4(focus
) = CHILDID_SELF
;
369 else if(IsChild(This
->hwnd
, info
.hwndFocus
)) {
373 hr
= AccessibleObjectFromWindow(info
.hwndFocus
, OBJID_WINDOW
,
374 &IID_IDispatch
, (void**)&disp
);
380 V_VT(focus
) = VT_DISPATCH
;
381 V_DISPATCH(focus
) = disp
;
388 static HRESULT WINAPI
Client_get_accSelection(IAccessible
*iface
, VARIANT
*pvarID
)
390 Client
*This
= impl_from_Client(iface
);
391 FIXME("(%p)->(%p)\n", This
, pvarID
);
395 static HRESULT WINAPI
Client_get_accDefaultAction(IAccessible
*iface
,
396 VARIANT varID
, BSTR
*pszDefaultAction
)
398 Client
*This
= impl_from_Client(iface
);
400 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&varID
), pszDefaultAction
);
402 *pszDefaultAction
= NULL
;
403 if(convert_child_id(&varID
) != CHILDID_SELF
)
408 static HRESULT WINAPI
Client_accSelect(IAccessible
*iface
, LONG flagsSelect
, VARIANT varID
)
410 Client
*This
= impl_from_Client(iface
);
411 FIXME("(%p)->(%lx %s)\n", This
, flagsSelect
, debugstr_variant(&varID
));
415 static HRESULT WINAPI
Client_accLocation(IAccessible
*iface
, LONG
*pxLeft
,
416 LONG
*pyTop
, LONG
*pcxWidth
, LONG
*pcyHeight
, VARIANT varID
)
418 Client
*This
= impl_from_Client(iface
);
422 TRACE("(%p)->(%p %p %p %p %s)\n", This
, pxLeft
, pyTop
,
423 pcxWidth
, pcyHeight
, debugstr_variant(&varID
));
425 *pxLeft
= *pyTop
= *pcxWidth
= *pcyHeight
= 0;
426 if(convert_child_id(&varID
) != CHILDID_SELF
)
429 if(!GetClientRect(This
->hwnd
, &rect
))
434 MapWindowPoints(This
->hwnd
, NULL
, &pt
, 1);
440 MapWindowPoints(This
->hwnd
, NULL
, &pt
, 1);
441 *pcxWidth
= pt
.x
- *pxLeft
;
442 *pcyHeight
= pt
.y
- *pyTop
;
446 static HRESULT WINAPI
Client_accNavigate(IAccessible
*iface
,
447 LONG navDir
, VARIANT varStart
, VARIANT
*pvarEnd
)
449 Client
*This
= impl_from_Client(iface
);
450 FIXME("(%p)->(%ld %s %p)\n", This
, navDir
, debugstr_variant(&varStart
), pvarEnd
);
454 static HRESULT WINAPI
Client_accHitTest(IAccessible
*iface
,
455 LONG xLeft
, LONG yTop
, VARIANT
*pvarID
)
457 Client
*This
= impl_from_Client(iface
);
461 TRACE("(%p)->(%ld %ld %p)\n", This
, xLeft
, yTop
, pvarID
);
463 V_VT(pvarID
) = VT_I4
;
468 if(!IsWindowVisible(This
->hwnd
) || !ScreenToClient(This
->hwnd
, &pt
))
471 child
= ChildWindowFromPointEx(This
->hwnd
, pt
, CWP_SKIPINVISIBLE
);
472 if(!child
|| child
==This
->hwnd
)
475 V_VT(pvarID
) = VT_DISPATCH
;
476 return AccessibleObjectFromWindow(child
, OBJID_WINDOW
,
477 &IID_IDispatch
, (void**)&V_DISPATCH(pvarID
));
480 static HRESULT WINAPI
Client_accDoDefaultAction(IAccessible
*iface
, VARIANT varID
)
482 Client
*This
= impl_from_Client(iface
);
483 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&varID
));
487 static HRESULT WINAPI
Client_put_accName(IAccessible
*iface
, VARIANT varID
, BSTR pszName
)
489 Client
*This
= impl_from_Client(iface
);
490 FIXME("(%p)->(%s %s)\n", This
, debugstr_variant(&varID
), debugstr_w(pszName
));
494 static HRESULT WINAPI
Client_put_accValue(IAccessible
*iface
, VARIANT id
, BSTR value
)
496 Client
*This
= impl_from_Client(iface
);
498 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(&id
), value
);
500 if(This
->vtbl
&& This
->vtbl
->put_value
)
501 return This
->vtbl
->put_value(This
, id
, value
);
503 if(convert_child_id(&id
) != CHILDID_SELF
)
508 static const IAccessibleVtbl ClientVtbl
= {
509 Client_QueryInterface
,
512 Client_GetTypeInfoCount
,
514 Client_GetIDsOfNames
,
516 Client_get_accParent
,
517 Client_get_accChildCount
,
521 Client_get_accDescription
,
525 Client_get_accHelpTopic
,
526 Client_get_accKeyboardShortcut
,
528 Client_get_accSelection
,
529 Client_get_accDefaultAction
,
534 Client_accDoDefaultAction
,
539 static inline Client
* impl_from_Client_OleWindow(IOleWindow
*iface
)
541 return CONTAINING_RECORD(iface
, Client
, IOleWindow_iface
);
544 static HRESULT WINAPI
Client_OleWindow_QueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppv
)
546 Client
*This
= impl_from_Client_OleWindow(iface
);
547 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, ppv
);
550 static ULONG WINAPI
Client_OleWindow_AddRef(IOleWindow
*iface
)
552 Client
*This
= impl_from_Client_OleWindow(iface
);
553 return IAccessible_AddRef(&This
->IAccessible_iface
);
556 static ULONG WINAPI
Client_OleWindow_Release(IOleWindow
*iface
)
558 Client
*This
= impl_from_Client_OleWindow(iface
);
559 return IAccessible_Release(&This
->IAccessible_iface
);
562 static HRESULT WINAPI
Client_OleWindow_GetWindow(IOleWindow
*iface
, HWND
*phwnd
)
564 Client
*This
= impl_from_Client_OleWindow(iface
);
566 TRACE("(%p)->(%p)\n", This
, phwnd
);
572 static HRESULT WINAPI
Client_OleWindow_ContextSensitiveHelp(IOleWindow
*iface
, BOOL fEnterMode
)
574 Client
*This
= impl_from_Client_OleWindow(iface
);
575 FIXME("(%p)->(%x)\n", This
, fEnterMode
);
579 static const IOleWindowVtbl ClientOleWindowVtbl
= {
580 Client_OleWindow_QueryInterface
,
581 Client_OleWindow_AddRef
,
582 Client_OleWindow_Release
,
583 Client_OleWindow_GetWindow
,
584 Client_OleWindow_ContextSensitiveHelp
587 static inline Client
* impl_from_Client_EnumVARIANT(IEnumVARIANT
*iface
)
589 return CONTAINING_RECORD(iface
, Client
, IEnumVARIANT_iface
);
592 static HRESULT WINAPI
Client_EnumVARIANT_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **ppv
)
594 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
595 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, ppv
);
598 static ULONG WINAPI
Client_EnumVARIANT_AddRef(IEnumVARIANT
*iface
)
600 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
601 return IAccessible_AddRef(&This
->IAccessible_iface
);
604 static ULONG WINAPI
Client_EnumVARIANT_Release(IEnumVARIANT
*iface
)
606 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
607 return IAccessible_Release(&This
->IAccessible_iface
);
610 static HRESULT WINAPI
Client_EnumVARIANT_Next(IEnumVARIANT
*iface
,
611 ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
613 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
614 HWND cur
= This
->enum_pos
, next
;
618 TRACE("(%p)->(%lu %p %p)\n", This
, celt
, rgVar
, pCeltFetched
);
627 next
= GetWindow(This
->hwnd
, GW_CHILD
);
629 next
= GetWindow(This
->enum_pos
, GW_HWNDNEXT
);
634 V_VT(rgVar
+fetched
) = VT_DISPATCH
;
635 hr
= AccessibleObjectFromWindow(cur
, OBJID_WINDOW
,
636 &IID_IDispatch
, (void**)&V_DISPATCH(rgVar
+fetched
));
638 V_VT(rgVar
+fetched
) = VT_EMPTY
;
640 VariantClear(rgVar
+fetched
-1);
651 next
= GetWindow(cur
, GW_HWNDNEXT
);
654 This
->enum_pos
= cur
;
656 *pCeltFetched
= fetched
;
657 return celt
== fetched
? S_OK
: S_FALSE
;
660 static HRESULT WINAPI
Client_EnumVARIANT_Skip(IEnumVARIANT
*iface
, ULONG celt
)
662 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
665 TRACE("(%p)->(%lu)\n", This
, celt
);
669 next
= GetWindow(This
->hwnd
, GW_CHILD
);
671 next
= GetWindow(This
->enum_pos
, GW_HWNDNEXT
);
675 This
->enum_pos
= next
;
682 static HRESULT WINAPI
Client_EnumVARIANT_Reset(IEnumVARIANT
*iface
)
684 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
686 TRACE("(%p)\n", This
);
692 static HRESULT WINAPI
Client_EnumVARIANT_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
694 Client
*This
= impl_from_Client_EnumVARIANT(iface
);
695 FIXME("(%p)->(%p)\n", This
, ppEnum
);
699 static const IEnumVARIANTVtbl ClientEnumVARIANTVtbl
= {
700 Client_EnumVARIANT_QueryInterface
,
701 Client_EnumVARIANT_AddRef
,
702 Client_EnumVARIANT_Release
,
703 Client_EnumVARIANT_Next
,
704 Client_EnumVARIANT_Skip
,
705 Client_EnumVARIANT_Reset
,
706 Client_EnumVARIANT_Clone
709 static inline Client
* impl_from_Client_ServiceProvider(IServiceProvider
*iface
)
711 return CONTAINING_RECORD(iface
, Client
, IServiceProvider_iface
);
714 static HRESULT WINAPI
Client_ServiceProvider_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **ppv
)
716 Client
*This
= impl_from_Client_ServiceProvider(iface
);
717 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, ppv
);
720 static ULONG WINAPI
Client_ServiceProvider_AddRef(IServiceProvider
*iface
)
722 Client
*This
= impl_from_Client_ServiceProvider(iface
);
723 return IAccessible_AddRef(&This
->IAccessible_iface
);
726 static ULONG WINAPI
Client_ServiceProvider_Release(IServiceProvider
*iface
)
728 Client
*This
= impl_from_Client_ServiceProvider(iface
);
729 return IAccessible_Release(&This
->IAccessible_iface
);
732 static HRESULT WINAPI
Client_ServiceProvider_QueryService(IServiceProvider
*iface
, REFGUID guid_service
,
733 REFIID riid
, void **ppv
)
735 Client
*This
= impl_from_Client_ServiceProvider(iface
);
737 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_guid(guid_service
), debugstr_guid(riid
), ppv
);
740 if (IsEqualIID(guid_service
, &IIS_IsOleaccProxy
))
741 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, ppv
);
746 static const IServiceProviderVtbl ClientServiceProviderVtbl
= {
747 Client_ServiceProvider_QueryInterface
,
748 Client_ServiceProvider_AddRef
,
749 Client_ServiceProvider_Release
,
750 Client_ServiceProvider_QueryService
753 static void edit_init(Client
*client
)
755 client
->role
= ROLE_SYSTEM_TEXT
;
758 static HRESULT
edit_get_state(Client
*client
, VARIANT id
, VARIANT
*state
)
763 hres
= client_get_state(client
, id
, state
);
767 assert(V_VT(state
) == VT_I4
);
769 style
= GetWindowLongW(client
->hwnd
, GWL_STYLE
);
770 if(style
& ES_READONLY
)
771 V_I4(state
) |= STATE_SYSTEM_READONLY
;
772 if(style
& ES_PASSWORD
)
773 V_I4(state
) |= STATE_SYSTEM_PROTECTED
;
778 * Edit control objects have their name property defined by the first static
779 * text control preceding them in the order of window creation. If one is not
780 * found, the edit has no name property. In the case of the keyboard shortcut
781 * property, the first preceding visible static text control is used.
783 static HWND
edit_find_label(HWND hwnd
, BOOL visible
)
787 for(cur
= hwnd
; cur
; cur
= GetWindow(cur
, GW_HWNDPREV
)) {
788 WCHAR class_name
[64];
790 if(!RealGetWindowClassW(cur
, class_name
, ARRAY_SIZE(class_name
)))
793 if(!wcsicmp(class_name
, WC_STATICW
)) {
794 if(visible
&& !(GetWindowLongW(cur
, GWL_STYLE
) & WS_VISIBLE
))
804 static HRESULT
edit_get_name(Client
*client
, VARIANT id
, BSTR
*name
)
808 if(convert_child_id(&id
) != CHILDID_SELF
|| !IsWindow(client
->hwnd
))
811 label
= edit_find_label(client
->hwnd
, FALSE
);
815 return win_get_name(label
, name
);
818 static HRESULT
edit_get_kbd_shortcut(Client
*client
, VARIANT id
, BSTR
*shortcut
)
822 if(convert_child_id(&id
) != CHILDID_SELF
)
825 label
= edit_find_label(client
->hwnd
, TRUE
);
829 return win_get_kbd_shortcut(label
, shortcut
);
832 static HRESULT
edit_get_value(Client
*client
, VARIANT id
, BSTR
*value_out
)
837 if(convert_child_id(&id
) != CHILDID_SELF
)
840 if(GetWindowLongW(client
->hwnd
, GWL_STYLE
) & ES_PASSWORD
)
841 return E_ACCESSDENIED
;
843 len
= SendMessageW(client
->hwnd
, WM_GETTEXTLENGTH
, 0, 0);
844 buf
= heap_alloc_zero((len
+ 1) * sizeof(*buf
));
846 return E_OUTOFMEMORY
;
848 SendMessageW(client
->hwnd
, WM_GETTEXT
, len
+ 1, (LPARAM
)buf
);
849 *value_out
= SysAllocString(buf
);
854 static HRESULT
edit_put_value(Client
*client
, VARIANT id
, BSTR value
)
856 if(convert_child_id(&id
) != CHILDID_SELF
|| !IsWindow(client
->hwnd
))
859 SendMessageW(client
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)value
);
863 static const win_class_vtbl edit_vtbl
= {
867 edit_get_kbd_shortcut
,
872 static const struct win_class_data classes
[] = {
873 {WC_LISTBOXW
, 0x10000, TRUE
},
874 {L
"#32768", 0x10001, TRUE
}, /* menu */
875 {WC_BUTTONW
, 0x10002, TRUE
},
876 {WC_STATICW
, 0x10003, TRUE
},
877 {WC_EDITW
, 0x10004, FALSE
, &edit_vtbl
},
878 {WC_COMBOBOXW
, 0x10005, TRUE
},
879 {L
"#32770", 0x10006, TRUE
}, /* dialog */
880 {L
"#32771", 0x10007, TRUE
}, /* winswitcher */
881 {L
"MDIClient", 0x10008, TRUE
},
882 {L
"#32769", 0x10009, TRUE
}, /* desktop */
883 {WC_SCROLLBARW
, 0x1000a, TRUE
},
884 {STATUSCLASSNAMEW
, 0x1000b, TRUE
},
885 {TOOLBARCLASSNAMEW
, 0x1000c, TRUE
},
886 {PROGRESS_CLASSW
, 0x1000d, TRUE
},
887 {ANIMATE_CLASSW
, 0x1000e, TRUE
},
888 {WC_TABCONTROLW
, 0x1000f, TRUE
},
889 {HOTKEY_CLASSW
, 0x10010, TRUE
},
890 {WC_HEADERW
, 0x10011, TRUE
},
891 {TRACKBAR_CLASSW
, 0x10012, TRUE
},
892 {WC_LISTVIEWW
, 0x10013, TRUE
},
893 {UPDOWN_CLASSW
, 0x10016, TRUE
},
894 {TOOLTIPS_CLASSW
, 0x10018, TRUE
},
895 {WC_TREEVIEWW
, 0x10019, TRUE
},
896 {DATETIMEPICK_CLASSW
, 0, TRUE
},
897 {WC_IPADDRESSW
, 0, TRUE
},
898 {L
"RICHEDIT", 0x1001c, TRUE
},
899 {L
"RichEdit20A", 0, TRUE
},
900 {L
"RichEdit20W", 0, TRUE
},
904 HRESULT
create_client_object(HWND hwnd
, const IID
*iid
, void **obj
)
906 const struct win_class_data
*data
;
913 client
= heap_alloc_zero(sizeof(Client
));
915 return E_OUTOFMEMORY
;
917 data
= find_class_data(hwnd
, classes
);
919 client
->IAccessible_iface
.lpVtbl
= &ClientVtbl
;
920 client
->IOleWindow_iface
.lpVtbl
= &ClientOleWindowVtbl
;
921 client
->IEnumVARIANT_iface
.lpVtbl
= &ClientEnumVARIANTVtbl
;
922 client
->IServiceProvider_iface
.lpVtbl
= &ClientServiceProviderVtbl
;
925 client
->enum_pos
= 0;
926 client
->role
= ROLE_SYSTEM_CLIENT
;
929 client
->vtbl
= data
->vtbl
;
930 if(client
->vtbl
&& client
->vtbl
->init
)
931 client
->vtbl
->init(client
);
933 hres
= IAccessible_QueryInterface(&client
->IAccessible_iface
, iid
, obj
);
934 IAccessible_Release(&client
->IAccessible_iface
);