msdasql: Support IRowsetInfo in IRowset interface.
[wine.git] / dlls / oleacc / client.c
blob192a006bdbafe2794a5bb535b68df7cf9e35b175
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 <assert.h>
22 #include "oleacc_private.h"
23 #include "commctrl.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;
31 typedef struct {
32 IAccessible IAccessible_iface;
33 IOleWindow IOleWindow_iface;
34 IEnumVARIANT IEnumVARIANT_iface;
36 LONG ref;
38 HWND hwnd;
39 HWND enum_pos;
40 INT role;
42 const win_class_vtbl *vtbl;
43 } Client;
45 struct win_class_vtbl {
46 void (*init)(Client*);
47 HRESULT (*get_state)(Client*, VARIANT, VARIANT*);
48 HRESULT (*get_name)(Client*, VARIANT, BSTR*);
49 HRESULT (*get_kbd_shortcut)(Client*, VARIANT, BSTR*);
50 HRESULT (*get_value)(Client*, VARIANT, BSTR*);
51 HRESULT (*put_value)(Client*, VARIANT, BSTR);
54 static HRESULT win_get_name(HWND hwnd, BSTR *name)
56 WCHAR buf[1024];
57 UINT i, len;
59 len = SendMessageW(hwnd, WM_GETTEXT, ARRAY_SIZE(buf), (LPARAM)buf);
60 if(!len)
61 return S_FALSE;
63 for(i=0; i<len; i++) {
64 if(buf[i] == '&') {
65 len--;
66 memmove(buf+i, buf+i+1, (len-i)*sizeof(WCHAR));
67 break;
71 *name = SysAllocStringLen(buf, len);
72 return *name ? S_OK : E_OUTOFMEMORY;
75 static HRESULT win_get_kbd_shortcut(HWND hwnd, BSTR *shortcut)
77 WCHAR buf[1024];
78 UINT i, len;
80 len = SendMessageW(hwnd, WM_GETTEXT, ARRAY_SIZE(buf), (LPARAM)buf);
81 if(!len)
82 return S_FALSE;
84 for(i=0; i<len; i++) {
85 if(buf[i] == '&')
86 break;
88 if(i+1 >= len)
89 return S_FALSE;
91 *shortcut = SysAllocString(L"Alt+!");
92 if(!*shortcut)
93 return E_OUTOFMEMORY;
94 (*shortcut)[4] = buf[i+1];
95 return S_OK;
98 static inline Client* impl_from_Client(IAccessible *iface)
100 return CONTAINING_RECORD(iface, Client, IAccessible_iface);
103 static HRESULT WINAPI Client_QueryInterface(IAccessible *iface, REFIID riid, void **ppv)
105 Client *This = impl_from_Client(iface);
107 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
109 if(IsEqualIID(riid, &IID_IAccessible) ||
110 IsEqualIID(riid, &IID_IDispatch) ||
111 IsEqualIID(riid, &IID_IUnknown)) {
112 *ppv = iface;
113 }else if(IsEqualIID(riid, &IID_IOleWindow)) {
114 *ppv = &This->IOleWindow_iface;
115 }else if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
116 *ppv = &This->IEnumVARIANT_iface;
117 }else {
118 WARN("no interface: %s\n", debugstr_guid(riid));
119 *ppv = NULL;
120 return E_NOINTERFACE;
123 IAccessible_AddRef(iface);
124 return S_OK;
127 static ULONG WINAPI Client_AddRef(IAccessible *iface)
129 Client *This = impl_from_Client(iface);
130 ULONG ref = InterlockedIncrement(&This->ref);
132 TRACE("(%p) ref = %u\n", This, ref);
133 return ref;
136 static ULONG WINAPI Client_Release(IAccessible *iface)
138 Client *This = impl_from_Client(iface);
139 ULONG ref = InterlockedDecrement(&This->ref);
141 TRACE("(%p) ref = %u\n", This, ref);
143 if(!ref)
144 heap_free(This);
145 return ref;
148 static HRESULT WINAPI Client_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
150 Client *This = impl_from_Client(iface);
151 FIXME("(%p)->(%p)\n", This, pctinfo);
152 return E_NOTIMPL;
155 static HRESULT WINAPI Client_GetTypeInfo(IAccessible *iface,
156 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
158 Client *This = impl_from_Client(iface);
159 FIXME("(%p)->(%u %x %p)\n", This, iTInfo, lcid, ppTInfo);
160 return E_NOTIMPL;
163 static HRESULT WINAPI Client_GetIDsOfNames(IAccessible *iface, REFIID riid,
164 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
166 Client *This = impl_from_Client(iface);
167 FIXME("(%p)->(%s %p %u %x %p)\n", This, debugstr_guid(riid),
168 rgszNames, cNames, lcid, rgDispId);
169 return E_NOTIMPL;
172 static HRESULT WINAPI Client_Invoke(IAccessible *iface, DISPID dispIdMember,
173 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
174 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
176 Client *This = impl_from_Client(iface);
177 FIXME("(%p)->(%x %s %x %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
178 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
179 return E_NOTIMPL;
182 static HRESULT WINAPI Client_get_accParent(IAccessible *iface, IDispatch **ppdispParent)
184 Client *This = impl_from_Client(iface);
186 TRACE("(%p)->(%p)\n", This, ppdispParent);
188 return AccessibleObjectFromWindow(This->hwnd, OBJID_WINDOW,
189 &IID_IDispatch, (void**)ppdispParent);
192 static HRESULT WINAPI Client_get_accChildCount(IAccessible *iface, LONG *pcountChildren)
194 Client *This = impl_from_Client(iface);
195 HWND cur;
197 TRACE("(%p)->(%p)\n", This, pcountChildren);
199 *pcountChildren = 0;
200 for(cur = GetWindow(This->hwnd, GW_CHILD); cur; cur = GetWindow(cur, GW_HWNDNEXT))
201 (*pcountChildren)++;
203 return S_OK;
206 static HRESULT WINAPI Client_get_accChild(IAccessible *iface,
207 VARIANT varChildID, IDispatch **ppdispChild)
209 Client *This = impl_from_Client(iface);
211 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varChildID), ppdispChild);
213 *ppdispChild = NULL;
214 return E_INVALIDARG;
217 static HRESULT WINAPI Client_get_accName(IAccessible *iface, VARIANT id, BSTR *name)
219 Client *This = impl_from_Client(iface);
221 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&id), name);
223 *name = NULL;
224 if(This->vtbl && This->vtbl->get_name)
225 return This->vtbl->get_name(This, id, name);
227 if(convert_child_id(&id) != CHILDID_SELF || !IsWindow(This->hwnd))
228 return E_INVALIDARG;
230 return win_get_name(This->hwnd, name);
233 static HRESULT WINAPI Client_get_accValue(IAccessible *iface, VARIANT id, BSTR *value)
235 Client *This = impl_from_Client(iface);
237 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&id), value);
239 *value = NULL;
240 if(This->vtbl && This->vtbl->get_value)
241 return This->vtbl->get_value(This, id, value);
243 if(convert_child_id(&id) != CHILDID_SELF)
244 return E_INVALIDARG;
245 return S_FALSE;
248 static HRESULT WINAPI Client_get_accDescription(IAccessible *iface,
249 VARIANT varID, BSTR *pszDescription)
251 Client *This = impl_from_Client(iface);
253 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDescription);
255 *pszDescription = NULL;
256 if(convert_child_id(&varID) != CHILDID_SELF)
257 return E_INVALIDARG;
258 return S_FALSE;
261 static HRESULT WINAPI Client_get_accRole(IAccessible *iface, VARIANT varID, VARIANT *pvarRole)
263 Client *This = impl_from_Client(iface);
265 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarRole);
267 if(convert_child_id(&varID) != CHILDID_SELF) {
268 V_VT(pvarRole) = VT_EMPTY;
269 return E_INVALIDARG;
272 V_VT(pvarRole) = VT_I4;
273 V_I4(pvarRole) = This->role;
274 return S_OK;
277 static HRESULT client_get_state(Client *client, VARIANT id, VARIANT *state)
279 GUITHREADINFO info;
280 LONG style;
282 if(convert_child_id(&id) != CHILDID_SELF) {
283 V_VT(state) = VT_EMPTY;
284 return E_INVALIDARG;
287 V_VT(state) = VT_I4;
288 V_I4(state) = 0;
290 style = GetWindowLongW(client->hwnd, GWL_STYLE);
291 if(style & WS_DISABLED)
292 V_I4(state) |= STATE_SYSTEM_UNAVAILABLE;
293 else if(IsWindow(client->hwnd))
294 V_I4(state) |= STATE_SYSTEM_FOCUSABLE;
296 info.cbSize = sizeof(info);
297 if(GetGUIThreadInfo(0, &info) && info.hwndFocus == client->hwnd)
298 V_I4(state) |= STATE_SYSTEM_FOCUSED;
299 if(!(style & WS_VISIBLE))
300 V_I4(state) |= STATE_SYSTEM_INVISIBLE;
301 return S_OK;
304 static HRESULT WINAPI Client_get_accState(IAccessible *iface, VARIANT id, VARIANT *state)
306 Client *This = impl_from_Client(iface);
308 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&id), state);
310 if(This->vtbl && This->vtbl->get_state)
311 return This->vtbl->get_state(This, id, state);
312 return client_get_state(This, id, state);
315 static HRESULT WINAPI Client_get_accHelp(IAccessible *iface, VARIANT varID, BSTR *pszHelp)
317 Client *This = impl_from_Client(iface);
319 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszHelp);
321 *pszHelp = NULL;
322 if(convert_child_id(&varID) != CHILDID_SELF)
323 return E_INVALIDARG;
324 return S_FALSE;
327 static HRESULT WINAPI Client_get_accHelpTopic(IAccessible *iface,
328 BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic)
330 Client *This = impl_from_Client(iface);
331 FIXME("(%p)->(%p %s %p)\n", This, pszHelpFile, debugstr_variant(&varID), pidTopic);
332 return E_NOTIMPL;
335 static HRESULT WINAPI Client_get_accKeyboardShortcut(IAccessible *iface,
336 VARIANT id, BSTR *shortcut)
338 Client *This = impl_from_Client(iface);
340 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&id), shortcut);
342 *shortcut = NULL;
343 if(This->vtbl && This->vtbl->get_kbd_shortcut)
344 return This->vtbl->get_kbd_shortcut(This, id, shortcut);
346 if(convert_child_id(&id) != CHILDID_SELF)
347 return E_INVALIDARG;
349 return win_get_kbd_shortcut(This->hwnd, shortcut);
352 static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *focus)
354 Client *This = impl_from_Client(iface);
355 GUITHREADINFO info;
357 TRACE("(%p)->(%p)\n", This, focus);
359 V_VT(focus) = VT_EMPTY;
360 info.cbSize = sizeof(info);
361 if(GetGUIThreadInfo(0, &info) && info.hwndFocus) {
362 if(info.hwndFocus == This->hwnd) {
363 V_VT(focus) = VT_I4;
364 V_I4(focus) = CHILDID_SELF;
366 else if(IsChild(This->hwnd, info.hwndFocus)) {
367 IDispatch *disp;
368 HRESULT hr;
370 hr = AccessibleObjectFromWindow(info.hwndFocus, OBJID_WINDOW,
371 &IID_IDispatch, (void**)&disp);
372 if(FAILED(hr))
373 return hr;
374 if(!disp)
375 return E_FAIL;
377 V_VT(focus) = VT_DISPATCH;
378 V_DISPATCH(focus) = disp;
382 return S_OK;
385 static HRESULT WINAPI Client_get_accSelection(IAccessible *iface, VARIANT *pvarID)
387 Client *This = impl_from_Client(iface);
388 FIXME("(%p)->(%p)\n", This, pvarID);
389 return E_NOTIMPL;
392 static HRESULT WINAPI Client_get_accDefaultAction(IAccessible *iface,
393 VARIANT varID, BSTR *pszDefaultAction)
395 Client *This = impl_from_Client(iface);
397 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDefaultAction);
399 *pszDefaultAction = NULL;
400 if(convert_child_id(&varID) != CHILDID_SELF)
401 return E_INVALIDARG;
402 return S_FALSE;
405 static HRESULT WINAPI Client_accSelect(IAccessible *iface, LONG flagsSelect, VARIANT varID)
407 Client *This = impl_from_Client(iface);
408 FIXME("(%p)->(%x %s)\n", This, flagsSelect, debugstr_variant(&varID));
409 return E_NOTIMPL;
412 static HRESULT WINAPI Client_accLocation(IAccessible *iface, LONG *pxLeft,
413 LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID)
415 Client *This = impl_from_Client(iface);
416 RECT rect;
417 POINT pt;
419 TRACE("(%p)->(%p %p %p %p %s)\n", This, pxLeft, pyTop,
420 pcxWidth, pcyHeight, debugstr_variant(&varID));
422 *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
423 if(convert_child_id(&varID) != CHILDID_SELF)
424 return E_INVALIDARG;
426 if(!GetClientRect(This->hwnd, &rect))
427 return S_OK;
429 pt.x = rect.left;
430 pt.y = rect.top;
431 MapWindowPoints(This->hwnd, NULL, &pt, 1);
432 *pxLeft = pt.x;
433 *pyTop = pt.y;
435 pt.x = rect.right;
436 pt.y = rect.bottom;
437 MapWindowPoints(This->hwnd, NULL, &pt, 1);
438 *pcxWidth = pt.x - *pxLeft;
439 *pcyHeight = pt.y - *pyTop;
440 return S_OK;
443 static HRESULT WINAPI Client_accNavigate(IAccessible *iface,
444 LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
446 Client *This = impl_from_Client(iface);
447 FIXME("(%p)->(%d %s %p)\n", This, navDir, debugstr_variant(&varStart), pvarEnd);
448 return E_NOTIMPL;
451 static HRESULT WINAPI Client_accHitTest(IAccessible *iface,
452 LONG xLeft, LONG yTop, VARIANT *pvarID)
454 Client *This = impl_from_Client(iface);
455 HWND child;
456 POINT pt;
458 TRACE("(%p)->(%d %d %p)\n", This, xLeft, yTop, pvarID);
460 V_VT(pvarID) = VT_I4;
461 V_I4(pvarID) = 0;
463 pt.x = xLeft;
464 pt.y = yTop;
465 if(!IsWindowVisible(This->hwnd) || !ScreenToClient(This->hwnd, &pt))
466 return S_OK;
468 child = ChildWindowFromPointEx(This->hwnd, pt, CWP_SKIPINVISIBLE);
469 if(!child || child==This->hwnd)
470 return S_OK;
472 V_VT(pvarID) = VT_DISPATCH;
473 return AccessibleObjectFromWindow(child, OBJID_WINDOW,
474 &IID_IDispatch, (void**)&V_DISPATCH(pvarID));
477 static HRESULT WINAPI Client_accDoDefaultAction(IAccessible *iface, VARIANT varID)
479 Client *This = impl_from_Client(iface);
480 FIXME("(%p)->(%s)\n", This, debugstr_variant(&varID));
481 return E_NOTIMPL;
484 static HRESULT WINAPI Client_put_accName(IAccessible *iface, VARIANT varID, BSTR pszName)
486 Client *This = impl_from_Client(iface);
487 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszName));
488 return E_NOTIMPL;
491 static HRESULT WINAPI Client_put_accValue(IAccessible *iface, VARIANT id, BSTR value)
493 Client *This = impl_from_Client(iface);
495 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&id), value);
497 if(This->vtbl && This->vtbl->put_value)
498 return This->vtbl->put_value(This, id, value);
500 if(convert_child_id(&id) != CHILDID_SELF)
501 return E_INVALIDARG;
502 return S_FALSE;
505 static const IAccessibleVtbl ClientVtbl = {
506 Client_QueryInterface,
507 Client_AddRef,
508 Client_Release,
509 Client_GetTypeInfoCount,
510 Client_GetTypeInfo,
511 Client_GetIDsOfNames,
512 Client_Invoke,
513 Client_get_accParent,
514 Client_get_accChildCount,
515 Client_get_accChild,
516 Client_get_accName,
517 Client_get_accValue,
518 Client_get_accDescription,
519 Client_get_accRole,
520 Client_get_accState,
521 Client_get_accHelp,
522 Client_get_accHelpTopic,
523 Client_get_accKeyboardShortcut,
524 Client_get_accFocus,
525 Client_get_accSelection,
526 Client_get_accDefaultAction,
527 Client_accSelect,
528 Client_accLocation,
529 Client_accNavigate,
530 Client_accHitTest,
531 Client_accDoDefaultAction,
532 Client_put_accName,
533 Client_put_accValue
536 static inline Client* impl_from_Client_OleWindow(IOleWindow *iface)
538 return CONTAINING_RECORD(iface, Client, IOleWindow_iface);
541 static HRESULT WINAPI Client_OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **ppv)
543 Client *This = impl_from_Client_OleWindow(iface);
544 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
547 static ULONG WINAPI Client_OleWindow_AddRef(IOleWindow *iface)
549 Client *This = impl_from_Client_OleWindow(iface);
550 return IAccessible_AddRef(&This->IAccessible_iface);
553 static ULONG WINAPI Client_OleWindow_Release(IOleWindow *iface)
555 Client *This = impl_from_Client_OleWindow(iface);
556 return IAccessible_Release(&This->IAccessible_iface);
559 static HRESULT WINAPI Client_OleWindow_GetWindow(IOleWindow *iface, HWND *phwnd)
561 Client *This = impl_from_Client_OleWindow(iface);
563 TRACE("(%p)->(%p)\n", This, phwnd);
565 *phwnd = This->hwnd;
566 return S_OK;
569 static HRESULT WINAPI Client_OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMode)
571 Client *This = impl_from_Client_OleWindow(iface);
572 FIXME("(%p)->(%x)\n", This, fEnterMode);
573 return E_NOTIMPL;
576 static const IOleWindowVtbl ClientOleWindowVtbl = {
577 Client_OleWindow_QueryInterface,
578 Client_OleWindow_AddRef,
579 Client_OleWindow_Release,
580 Client_OleWindow_GetWindow,
581 Client_OleWindow_ContextSensitiveHelp
584 static inline Client* impl_from_Client_EnumVARIANT(IEnumVARIANT *iface)
586 return CONTAINING_RECORD(iface, Client, IEnumVARIANT_iface);
589 static HRESULT WINAPI Client_EnumVARIANT_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
591 Client *This = impl_from_Client_EnumVARIANT(iface);
592 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
595 static ULONG WINAPI Client_EnumVARIANT_AddRef(IEnumVARIANT *iface)
597 Client *This = impl_from_Client_EnumVARIANT(iface);
598 return IAccessible_AddRef(&This->IAccessible_iface);
601 static ULONG WINAPI Client_EnumVARIANT_Release(IEnumVARIANT *iface)
603 Client *This = impl_from_Client_EnumVARIANT(iface);
604 return IAccessible_Release(&This->IAccessible_iface);
607 static HRESULT WINAPI Client_EnumVARIANT_Next(IEnumVARIANT *iface,
608 ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
610 Client *This = impl_from_Client_EnumVARIANT(iface);
611 HWND cur = This->enum_pos, next;
612 ULONG fetched = 0;
613 HRESULT hr;
615 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
617 if(!celt) {
618 if(pCeltFetched)
619 *pCeltFetched = 0;
620 return S_OK;
623 if(!This->enum_pos)
624 next = GetWindow(This->hwnd, GW_CHILD);
625 else
626 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
628 while(next) {
629 cur = next;
631 V_VT(rgVar+fetched) = VT_DISPATCH;
632 hr = AccessibleObjectFromWindow(cur, OBJID_WINDOW,
633 &IID_IDispatch, (void**)&V_DISPATCH(rgVar+fetched));
634 if(FAILED(hr)) {
635 V_VT(rgVar+fetched) = VT_EMPTY;
636 while(fetched > 0) {
637 VariantClear(rgVar+fetched-1);
638 fetched--;
640 if(pCeltFetched)
641 *pCeltFetched = 0;
642 return hr;
644 fetched++;
645 if(fetched == celt)
646 break;
648 next = GetWindow(cur, GW_HWNDNEXT);
651 This->enum_pos = cur;
652 if(pCeltFetched)
653 *pCeltFetched = fetched;
654 return celt == fetched ? S_OK : S_FALSE;
657 static HRESULT WINAPI Client_EnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt)
659 Client *This = impl_from_Client_EnumVARIANT(iface);
660 HWND next;
662 TRACE("(%p)->(%u)\n", This, celt);
664 while(celt) {
665 if(!This->enum_pos)
666 next = GetWindow(This->hwnd, GW_CHILD);
667 else
668 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
669 if(!next)
670 return S_FALSE;
672 This->enum_pos = next;
673 celt--;
676 return S_OK;
679 static HRESULT WINAPI Client_EnumVARIANT_Reset(IEnumVARIANT *iface)
681 Client *This = impl_from_Client_EnumVARIANT(iface);
683 TRACE("(%p)\n", This);
685 This->enum_pos = 0;
686 return S_OK;
689 static HRESULT WINAPI Client_EnumVARIANT_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
691 Client *This = impl_from_Client_EnumVARIANT(iface);
692 FIXME("(%p)->(%p)\n", This, ppEnum);
693 return E_NOTIMPL;
696 static const IEnumVARIANTVtbl ClientEnumVARIANTVtbl = {
697 Client_EnumVARIANT_QueryInterface,
698 Client_EnumVARIANT_AddRef,
699 Client_EnumVARIANT_Release,
700 Client_EnumVARIANT_Next,
701 Client_EnumVARIANT_Skip,
702 Client_EnumVARIANT_Reset,
703 Client_EnumVARIANT_Clone
706 static void edit_init(Client *client)
708 client->role = ROLE_SYSTEM_TEXT;
711 static HRESULT edit_get_state(Client *client, VARIANT id, VARIANT *state)
713 HRESULT hres;
714 LONG style;
716 hres = client_get_state(client, id, state);
717 if(FAILED(hres))
718 return hres;
720 assert(V_VT(state) == VT_I4);
722 style = GetWindowLongW(client->hwnd, GWL_STYLE);
723 if(style & ES_READONLY)
724 V_I4(state) |= STATE_SYSTEM_READONLY;
725 if(style & ES_PASSWORD)
726 V_I4(state) |= STATE_SYSTEM_PROTECTED;
727 return S_OK;
731 * Edit control objects have their name property defined by the first static
732 * text control preceding them in the order of window creation. If one is not
733 * found, the edit has no name property. In the case of the keyboard shortcut
734 * property, the first preceding visible static text control is used.
736 static HWND edit_find_label(HWND hwnd, BOOL visible)
738 HWND cur;
740 for(cur = hwnd; cur; cur = GetWindow(cur, GW_HWNDPREV)) {
741 WCHAR class_name[64];
743 if(!RealGetWindowClassW(cur, class_name, ARRAY_SIZE(class_name)))
744 continue;
746 if(!wcsicmp(class_name, WC_STATICW)) {
747 if(visible && !(GetWindowLongW(cur, GWL_STYLE) & WS_VISIBLE))
748 continue;
749 else
750 break;
754 return cur;
757 static HRESULT edit_get_name(Client *client, VARIANT id, BSTR *name)
759 HWND label;
761 if(convert_child_id(&id) != CHILDID_SELF || !IsWindow(client->hwnd))
762 return E_INVALIDARG;
764 label = edit_find_label(client->hwnd, FALSE);
765 if(!label)
766 return S_FALSE;
768 return win_get_name(label, name);
771 static HRESULT edit_get_kbd_shortcut(Client *client, VARIANT id, BSTR *shortcut)
773 HWND label;
775 if(convert_child_id(&id) != CHILDID_SELF)
776 return E_INVALIDARG;
778 label = edit_find_label(client->hwnd, TRUE);
779 if(!label)
780 return S_FALSE;
782 return win_get_kbd_shortcut(label, shortcut);
785 static HRESULT edit_get_value(Client *client, VARIANT id, BSTR *value_out)
787 WCHAR *buf;
788 UINT len;
790 if(convert_child_id(&id) != CHILDID_SELF)
791 return E_INVALIDARG;
793 if(GetWindowLongW(client->hwnd, GWL_STYLE) & ES_PASSWORD)
794 return E_ACCESSDENIED;
796 len = SendMessageW(client->hwnd, WM_GETTEXTLENGTH, 0, 0);
797 buf = heap_alloc_zero((len + 1) * sizeof(*buf));
798 if(!buf)
799 return E_OUTOFMEMORY;
801 SendMessageW(client->hwnd, WM_GETTEXT, len + 1, (LPARAM)buf);
802 *value_out = SysAllocString(buf);
803 heap_free(buf);
804 return S_OK;
807 static HRESULT edit_put_value(Client *client, VARIANT id, BSTR value)
809 if(convert_child_id(&id) != CHILDID_SELF || !IsWindow(client->hwnd))
810 return E_INVALIDARG;
812 SendMessageW(client->hwnd, WM_SETTEXT, 0, (LPARAM)value);
813 return S_OK;
816 static const win_class_vtbl edit_vtbl = {
817 edit_init,
818 edit_get_state,
819 edit_get_name,
820 edit_get_kbd_shortcut,
821 edit_get_value,
822 edit_put_value,
825 static const struct win_class_data classes[] = {
826 {WC_LISTBOXW, 0x10000, TRUE},
827 {L"#32768", 0x10001, TRUE}, /* menu */
828 {WC_BUTTONW, 0x10002, TRUE},
829 {WC_STATICW, 0x10003, TRUE},
830 {WC_EDITW, 0x10004, FALSE, &edit_vtbl},
831 {WC_COMBOBOXW, 0x10005, TRUE},
832 {L"#32770", 0x10006, TRUE}, /* dialog */
833 {L"#32771", 0x10007, TRUE}, /* winswitcher */
834 {L"MDIClient", 0x10008, TRUE},
835 {L"#32769", 0x10009, TRUE}, /* desktop */
836 {WC_SCROLLBARW, 0x1000a, TRUE},
837 {STATUSCLASSNAMEW, 0x1000b, TRUE},
838 {TOOLBARCLASSNAMEW, 0x1000c, TRUE},
839 {PROGRESS_CLASSW, 0x1000d, TRUE},
840 {ANIMATE_CLASSW, 0x1000e, TRUE},
841 {WC_TABCONTROLW, 0x1000f, TRUE},
842 {HOTKEY_CLASSW, 0x10010, TRUE},
843 {WC_HEADERW, 0x10011, TRUE},
844 {TRACKBAR_CLASSW, 0x10012, TRUE},
845 {WC_LISTVIEWW, 0x10013, TRUE},
846 {UPDOWN_CLASSW, 0x10016, TRUE},
847 {TOOLTIPS_CLASSW, 0x10018, TRUE},
848 {WC_TREEVIEWW, 0x10019, TRUE},
849 {DATETIMEPICK_CLASSW, 0, TRUE},
850 {WC_IPADDRESSW, 0, TRUE},
851 {L"RICHEDIT", 0x1001c, TRUE},
852 {L"RichEdit20A", 0, TRUE},
853 {L"RichEdit20W", 0, TRUE},
854 {NULL}
857 HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj)
859 const struct win_class_data *data;
860 Client *client;
861 HRESULT hres = S_OK;
863 if(!IsWindow(hwnd))
864 return E_FAIL;
866 client = heap_alloc_zero(sizeof(Client));
867 if(!client)
868 return E_OUTOFMEMORY;
870 data = find_class_data(hwnd, classes);
872 client->IAccessible_iface.lpVtbl = &ClientVtbl;
873 client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl;
874 client->IEnumVARIANT_iface.lpVtbl = &ClientEnumVARIANTVtbl;
875 client->ref = 1;
876 client->hwnd = hwnd;
877 client->enum_pos = 0;
878 client->role = ROLE_SYSTEM_CLIENT;
880 if(data)
881 client->vtbl = data->vtbl;
882 if(client->vtbl && client->vtbl->init)
883 client->vtbl->init(client);
885 hres = IAccessible_QueryInterface(&client->IAccessible_iface, iid, obj);
886 IAccessible_Release(&client->IAccessible_iface);
887 return hres;