ntdll/tests: Added more registry symlink tests.
[wine.git] / dlls / oleacc / client.c
blobddaa89dd66e77f40a65d09b623658ed8e6a310dd
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"
26 WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
28 typedef struct {
29 IAccessible IAccessible_iface;
30 IOleWindow IOleWindow_iface;
31 IEnumVARIANT IEnumVARIANT_iface;
33 LONG ref;
35 HWND hwnd;
36 HWND enum_pos;
37 } Client;
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)) {
53 *ppv = iface;
54 }else if(IsEqualIID(riid, &IID_IOleWindow)) {
55 *ppv = &This->IOleWindow_iface;
56 }else if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
57 *ppv = &This->IEnumVARIANT_iface;
58 }else {
59 WARN("no interface: %s\n", debugstr_guid(riid));
60 *ppv = NULL;
61 return E_NOINTERFACE;
64 IAccessible_AddRef(iface);
65 return S_OK;
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);
74 return 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);
84 if(!ref)
85 heap_free(This);
86 return 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);
93 return E_NOTIMPL;
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);
101 return E_NOTIMPL;
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);
110 return E_NOTIMPL;
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);
120 return E_NOTIMPL;
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);
136 HWND cur;
138 TRACE("(%p)->(%p)\n", This, pcountChildren);
140 *pcountChildren = 0;
141 for(cur = GetWindow(This->hwnd, GW_CHILD); cur; cur = GetWindow(cur, GW_HWNDNEXT))
142 (*pcountChildren)++;
144 return S_OK;
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);
154 *ppdispChild = NULL;
155 return E_INVALIDARG;
158 static HRESULT WINAPI Client_get_accName(IAccessible *iface, VARIANT varID, BSTR *pszName)
160 Client *This = impl_from_Client(iface);
161 WCHAR name[1024];
162 UINT i, len;
164 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszName);
166 *pszName = NULL;
167 if(convert_child_id(&varID) != CHILDID_SELF || !IsWindow(This->hwnd))
168 return E_INVALIDARG;
170 len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name);
171 if(!len)
172 return S_FALSE;
174 for(i=0; i<len; i++) {
175 if(name[i] == '&') {
176 len--;
177 memmove(name+i, name+i+1, (len-i)*sizeof(WCHAR));
178 break;
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);
192 *pszValue = NULL;
193 if(convert_child_id(&varID) != CHILDID_SELF)
194 return E_INVALIDARG;
195 return S_FALSE;
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)
207 return E_INVALIDARG;
208 return S_FALSE;
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;
219 return E_INVALIDARG;
222 V_VT(pvarRole) = VT_I4;
223 V_I4(pvarRole) = ROLE_SYSTEM_CLIENT;
224 return S_OK;
227 static HRESULT WINAPI Client_get_accState(IAccessible *iface, VARIANT varID, VARIANT *pvarState)
229 Client *This = impl_from_Client(iface);
230 LONG style;
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;
236 return E_INVALIDARG;
239 V_VT(pvarState) = VT_I4;
240 V_I4(pvarState) = 0;
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;
251 return S_OK;
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);
260 *pszHelp = NULL;
261 if(convert_child_id(&varID) != CHILDID_SELF)
262 return E_INVALIDARG;
263 return S_FALSE;
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);
271 return E_NOTIMPL;
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);
279 WCHAR name[1024];
280 UINT i, len;
282 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszKeyboardShortcut);
284 *pszKeyboardShortcut = NULL;
285 if(convert_child_id(&varID) != CHILDID_SELF)
286 return E_INVALIDARG;
288 len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name);
289 for(i=0; i<len; i++) {
290 if(name[i] == '&')
291 break;
293 if(i+1 >= len)
294 return S_FALSE;
296 *pszKeyboardShortcut = SysAllocString(shortcut_fmt);
297 if(!*pszKeyboardShortcut)
298 return E_OUTOFMEMORY;
300 (*pszKeyboardShortcut)[4] = name[i+1];
301 return S_OK;
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);
308 return E_NOTIMPL;
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);
315 return E_NOTIMPL;
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)
327 return E_INVALIDARG;
328 return S_FALSE;
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));
335 return E_NOTIMPL;
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);
342 RECT rect;
343 POINT pt;
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)
350 return E_INVALIDARG;
352 if(!GetClientRect(This->hwnd, &rect))
353 return S_OK;
355 pt.x = rect.left,
356 pt.y = rect.top;
357 MapWindowPoints(This->hwnd, NULL, &pt, 1);
358 *pxLeft = pt.x;
359 *pyTop = pt.y;
361 pt.x = rect.right;
362 pt.y = rect.bottom;
363 MapWindowPoints(This->hwnd, NULL, &pt, 1);
364 *pcxWidth = pt.x - *pxLeft;
365 *pcyHeight = pt.y - *pyTop;
366 return S_OK;
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);
374 return E_NOTIMPL;
377 static HRESULT WINAPI Client_accHitTest(IAccessible *iface,
378 LONG xLeft, LONG yTop, VARIANT *pvarID)
380 Client *This = impl_from_Client(iface);
381 HWND child;
382 POINT pt;
384 TRACE("(%p)->(%d %d %p)\n", This, xLeft, yTop, pvarID);
386 V_VT(pvarID) = VT_I4;
387 V_I4(pvarID) = 0;
389 pt.x = xLeft;
390 pt.y = yTop;
391 if(!IsWindowVisible(This->hwnd) || !ScreenToClient(This->hwnd, &pt))
392 return S_OK;
394 child = ChildWindowFromPointEx(This->hwnd, pt, CWP_SKIPINVISIBLE);
395 if(!child || child==This->hwnd)
396 return S_OK;
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));
407 return E_NOTIMPL;
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));
414 return E_NOTIMPL;
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));
421 return E_NOTIMPL;
424 static const IAccessibleVtbl ClientVtbl = {
425 Client_QueryInterface,
426 Client_AddRef,
427 Client_Release,
428 Client_GetTypeInfoCount,
429 Client_GetTypeInfo,
430 Client_GetIDsOfNames,
431 Client_Invoke,
432 Client_get_accParent,
433 Client_get_accChildCount,
434 Client_get_accChild,
435 Client_get_accName,
436 Client_get_accValue,
437 Client_get_accDescription,
438 Client_get_accRole,
439 Client_get_accState,
440 Client_get_accHelp,
441 Client_get_accHelpTopic,
442 Client_get_accKeyboardShortcut,
443 Client_get_accFocus,
444 Client_get_accSelection,
445 Client_get_accDefaultAction,
446 Client_accSelect,
447 Client_accLocation,
448 Client_accNavigate,
449 Client_accHitTest,
450 Client_accDoDefaultAction,
451 Client_put_accName,
452 Client_put_accValue
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);
484 *phwnd = This->hwnd;
485 return S_OK;
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);
492 return E_NOTIMPL;
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;
531 ULONG fetched = 0;
532 HRESULT hr;
534 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
536 if(!celt) {
537 if(pCeltFetched)
538 *pCeltFetched = 0;
539 return S_OK;
542 if(!This->enum_pos)
543 next = GetWindow(This->hwnd, GW_CHILD);
544 else
545 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
547 while(next) {
548 cur = next;
550 V_VT(rgVar+fetched) = VT_DISPATCH;
551 hr = AccessibleObjectFromWindow(cur, OBJID_WINDOW,
552 &IID_IDispatch, (void**)&V_DISPATCH(rgVar+fetched));
553 if(FAILED(hr)) {
554 V_VT(rgVar+fetched) = VT_EMPTY;
555 while(fetched > 0) {
556 VariantClear(rgVar+fetched-1);
557 fetched--;
559 if(pCeltFetched)
560 *pCeltFetched = 0;
561 return hr;
563 fetched++;
564 if(fetched == celt)
565 break;
567 next = GetWindow(cur, GW_HWNDNEXT);
570 This->enum_pos = cur;
571 if(pCeltFetched)
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);
579 HWND next;
581 TRACE("(%p)->(%u)\n", This, celt);
583 while(celt) {
584 if(!This->enum_pos)
585 next = GetWindow(This->hwnd, GW_CHILD);
586 else
587 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
588 if(!next)
589 return S_FALSE;
591 This->enum_pos = next;
592 celt--;
595 return S_OK;
598 static HRESULT WINAPI Client_EnumVARIANT_Reset(IEnumVARIANT *iface)
600 Client *This = impl_from_Client_EnumVARIANT(iface);
602 TRACE("(%p)\n", This);
604 This->enum_pos = 0;
605 return S_OK;
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);
612 return E_NOTIMPL;
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)
627 Client *client;
628 HRESULT hres;
630 if(!IsWindow(hwnd))
631 return E_FAIL;
633 client = heap_alloc_zero(sizeof(Client));
634 if(!client)
635 return E_OUTOFMEMORY;
637 client->IAccessible_iface.lpVtbl = &ClientVtbl;
638 client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl;
639 client->IEnumVARIANT_iface.lpVtbl = &ClientEnumVARIANTVtbl;
640 client->ref = 1;
641 client->hwnd = hwnd;
642 client->enum_pos = 0;
644 hres = IAccessible_QueryInterface(&client->IAccessible_iface, iid, obj);
645 IAccessible_Release(&client->IAccessible_iface);
646 return hres;