[OLEACC] Sync with Wine Staging 4.0. CORE-15682
[reactos.git] / dll / win32 / oleacc / client.c
1 /*
2 * Copyright 2014 Piotr Caban for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #define COBJMACROS
20
21 #include "oleacc_private.h"
22
23 #include "wine/unicode.h"
24 #include "wine/debug.h"
25 #include "wine/heap.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
28
29 typedef struct {
30 IAccessible IAccessible_iface;
31 IOleWindow IOleWindow_iface;
32 IEnumVARIANT IEnumVARIANT_iface;
33
34 LONG ref;
35
36 HWND hwnd;
37 HWND enum_pos;
38 } Client;
39
40 static inline Client* impl_from_Client(IAccessible *iface)
41 {
42 return CONTAINING_RECORD(iface, Client, IAccessible_iface);
43 }
44
45 static HRESULT WINAPI Client_QueryInterface(IAccessible *iface, REFIID riid, void **ppv)
46 {
47 Client *This = impl_from_Client(iface);
48
49 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
50
51 if(IsEqualIID(riid, &IID_IAccessible) ||
52 IsEqualIID(riid, &IID_IDispatch) ||
53 IsEqualIID(riid, &IID_IUnknown)) {
54 *ppv = iface;
55 }else if(IsEqualIID(riid, &IID_IOleWindow)) {
56 *ppv = &This->IOleWindow_iface;
57 }else if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
58 *ppv = &This->IEnumVARIANT_iface;
59 }else {
60 WARN("no interface: %s\n", debugstr_guid(riid));
61 *ppv = NULL;
62 return E_NOINTERFACE;
63 }
64
65 IAccessible_AddRef(iface);
66 return S_OK;
67 }
68
69 static ULONG WINAPI Client_AddRef(IAccessible *iface)
70 {
71 Client *This = impl_from_Client(iface);
72 ULONG ref = InterlockedIncrement(&This->ref);
73
74 TRACE("(%p) ref = %u\n", This, ref);
75 return ref;
76 }
77
78 static ULONG WINAPI Client_Release(IAccessible *iface)
79 {
80 Client *This = impl_from_Client(iface);
81 ULONG ref = InterlockedDecrement(&This->ref);
82
83 TRACE("(%p) ref = %u\n", This, ref);
84
85 if(!ref)
86 heap_free(This);
87 return ref;
88 }
89
90 static HRESULT WINAPI Client_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
91 {
92 Client *This = impl_from_Client(iface);
93 FIXME("(%p)->(%p)\n", This, pctinfo);
94 return E_NOTIMPL;
95 }
96
97 static HRESULT WINAPI Client_GetTypeInfo(IAccessible *iface,
98 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
99 {
100 Client *This = impl_from_Client(iface);
101 FIXME("(%p)->(%u %x %p)\n", This, iTInfo, lcid, ppTInfo);
102 return E_NOTIMPL;
103 }
104
105 static HRESULT WINAPI Client_GetIDsOfNames(IAccessible *iface, REFIID riid,
106 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
107 {
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);
111 return E_NOTIMPL;
112 }
113
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)
117 {
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);
121 return E_NOTIMPL;
122 }
123
124 static HRESULT WINAPI Client_get_accParent(IAccessible *iface, IDispatch **ppdispParent)
125 {
126 Client *This = impl_from_Client(iface);
127
128 TRACE("(%p)->(%p)\n", This, ppdispParent);
129
130 return AccessibleObjectFromWindow(This->hwnd, OBJID_WINDOW,
131 &IID_IDispatch, (void**)ppdispParent);
132 }
133
134 static HRESULT WINAPI Client_get_accChildCount(IAccessible *iface, LONG *pcountChildren)
135 {
136 Client *This = impl_from_Client(iface);
137 HWND cur;
138
139 TRACE("(%p)->(%p)\n", This, pcountChildren);
140
141 *pcountChildren = 0;
142 for(cur = GetWindow(This->hwnd, GW_CHILD); cur; cur = GetWindow(cur, GW_HWNDNEXT))
143 (*pcountChildren)++;
144
145 return S_OK;
146 }
147
148 static HRESULT WINAPI Client_get_accChild(IAccessible *iface,
149 VARIANT varChildID, IDispatch **ppdispChild)
150 {
151 Client *This = impl_from_Client(iface);
152
153 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varChildID), ppdispChild);
154
155 *ppdispChild = NULL;
156 return E_INVALIDARG;
157 }
158
159 static HRESULT WINAPI Client_get_accName(IAccessible *iface, VARIANT varID, BSTR *pszName)
160 {
161 Client *This = impl_from_Client(iface);
162 WCHAR name[1024];
163 UINT i, len;
164
165 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszName);
166
167 *pszName = NULL;
168 if(convert_child_id(&varID) != CHILDID_SELF || !IsWindow(This->hwnd))
169 return E_INVALIDARG;
170
171 len = SendMessageW(This->hwnd, WM_GETTEXT, ARRAY_SIZE(name), (LPARAM)name);
172 if(!len)
173 return S_FALSE;
174
175 for(i=0; i<len; i++) {
176 if(name[i] == '&') {
177 len--;
178 memmove(name+i, name+i+1, (len-i)*sizeof(WCHAR));
179 break;
180 }
181 }
182
183 *pszName = SysAllocStringLen(name, len);
184 return *pszName ? S_OK : E_OUTOFMEMORY;
185 }
186
187 static HRESULT WINAPI Client_get_accValue(IAccessible *iface, VARIANT varID, BSTR *pszValue)
188 {
189 Client *This = impl_from_Client(iface);
190
191 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszValue);
192
193 *pszValue = NULL;
194 if(convert_child_id(&varID) != CHILDID_SELF)
195 return E_INVALIDARG;
196 return S_FALSE;
197 }
198
199 static HRESULT WINAPI Client_get_accDescription(IAccessible *iface,
200 VARIANT varID, BSTR *pszDescription)
201 {
202 Client *This = impl_from_Client(iface);
203
204 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDescription);
205
206 *pszDescription = NULL;
207 if(convert_child_id(&varID) != CHILDID_SELF)
208 return E_INVALIDARG;
209 return S_FALSE;
210 }
211
212 static HRESULT WINAPI Client_get_accRole(IAccessible *iface, VARIANT varID, VARIANT *pvarRole)
213 {
214 Client *This = impl_from_Client(iface);
215
216 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarRole);
217
218 if(convert_child_id(&varID) != CHILDID_SELF) {
219 V_VT(pvarRole) = VT_EMPTY;
220 return E_INVALIDARG;
221 }
222
223 V_VT(pvarRole) = VT_I4;
224 V_I4(pvarRole) = ROLE_SYSTEM_CLIENT;
225 return S_OK;
226 }
227
228 static HRESULT WINAPI Client_get_accState(IAccessible *iface, VARIANT varID, VARIANT *pvarState)
229 {
230 Client *This = impl_from_Client(iface);
231 LONG style;
232
233 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarState);
234
235 if(convert_child_id(&varID) != CHILDID_SELF) {
236 V_VT(pvarState) = VT_EMPTY;
237 return E_INVALIDARG;
238 }
239
240 V_VT(pvarState) = VT_I4;
241 V_I4(pvarState) = 0;
242
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;
252 return S_OK;
253 }
254
255 static HRESULT WINAPI Client_get_accHelp(IAccessible *iface, VARIANT varID, BSTR *pszHelp)
256 {
257 Client *This = impl_from_Client(iface);
258
259 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszHelp);
260
261 *pszHelp = NULL;
262 if(convert_child_id(&varID) != CHILDID_SELF)
263 return E_INVALIDARG;
264 return S_FALSE;
265 }
266
267 static HRESULT WINAPI Client_get_accHelpTopic(IAccessible *iface,
268 BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic)
269 {
270 Client *This = impl_from_Client(iface);
271 FIXME("(%p)->(%p %s %p)\n", This, pszHelpFile, debugstr_variant(&varID), pidTopic);
272 return E_NOTIMPL;
273 }
274
275 static HRESULT WINAPI Client_get_accKeyboardShortcut(IAccessible *iface,
276 VARIANT varID, BSTR *pszKeyboardShortcut)
277 {
278 static const WCHAR shortcut_fmt[] = {'A','l','t','+','!',0};
279 Client *This = impl_from_Client(iface);
280 WCHAR name[1024];
281 UINT i, len;
282
283 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszKeyboardShortcut);
284
285 *pszKeyboardShortcut = NULL;
286 if(convert_child_id(&varID) != CHILDID_SELF)
287 return E_INVALIDARG;
288
289 len = SendMessageW(This->hwnd, WM_GETTEXT, ARRAY_SIZE(name), (LPARAM)name);
290 for(i=0; i<len; i++) {
291 if(name[i] == '&')
292 break;
293 }
294 if(i+1 >= len)
295 return S_FALSE;
296
297 *pszKeyboardShortcut = SysAllocString(shortcut_fmt);
298 if(!*pszKeyboardShortcut)
299 return E_OUTOFMEMORY;
300
301 (*pszKeyboardShortcut)[4] = name[i+1];
302 return S_OK;
303 }
304
305 static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *pvarID)
306 {
307 Client *This = impl_from_Client(iface);
308 FIXME("(%p)->(%p)\n", This, pvarID);
309 return E_NOTIMPL;
310 }
311
312 static HRESULT WINAPI Client_get_accSelection(IAccessible *iface, VARIANT *pvarID)
313 {
314 Client *This = impl_from_Client(iface);
315 FIXME("(%p)->(%p)\n", This, pvarID);
316 return E_NOTIMPL;
317 }
318
319 static HRESULT WINAPI Client_get_accDefaultAction(IAccessible *iface,
320 VARIANT varID, BSTR *pszDefaultAction)
321 {
322 Client *This = impl_from_Client(iface);
323
324 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDefaultAction);
325
326 *pszDefaultAction = NULL;
327 if(convert_child_id(&varID) != CHILDID_SELF)
328 return E_INVALIDARG;
329 return S_FALSE;
330 }
331
332 static HRESULT WINAPI Client_accSelect(IAccessible *iface, LONG flagsSelect, VARIANT varID)
333 {
334 Client *This = impl_from_Client(iface);
335 FIXME("(%p)->(%x %s)\n", This, flagsSelect, debugstr_variant(&varID));
336 return E_NOTIMPL;
337 }
338
339 static HRESULT WINAPI Client_accLocation(IAccessible *iface, LONG *pxLeft,
340 LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID)
341 {
342 Client *This = impl_from_Client(iface);
343 RECT rect;
344 POINT pt;
345
346 TRACE("(%p)->(%p %p %p %p %s)\n", This, pxLeft, pyTop,
347 pcxWidth, pcyHeight, debugstr_variant(&varID));
348
349 *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
350 if(convert_child_id(&varID) != CHILDID_SELF)
351 return E_INVALIDARG;
352
353 if(!GetClientRect(This->hwnd, &rect))
354 return S_OK;
355
356 pt.x = rect.left,
357 pt.y = rect.top;
358 MapWindowPoints(This->hwnd, NULL, &pt, 1);
359 *pxLeft = pt.x;
360 *pyTop = pt.y;
361
362 pt.x = rect.right;
363 pt.y = rect.bottom;
364 MapWindowPoints(This->hwnd, NULL, &pt, 1);
365 *pcxWidth = pt.x - *pxLeft;
366 *pcyHeight = pt.y - *pyTop;
367 return S_OK;
368 }
369
370 static HRESULT WINAPI Client_accNavigate(IAccessible *iface,
371 LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
372 {
373 Client *This = impl_from_Client(iface);
374 FIXME("(%p)->(%d %s %p)\n", This, navDir, debugstr_variant(&varStart), pvarEnd);
375 return E_NOTIMPL;
376 }
377
378 static HRESULT WINAPI Client_accHitTest(IAccessible *iface,
379 LONG xLeft, LONG yTop, VARIANT *pvarID)
380 {
381 Client *This = impl_from_Client(iface);
382 HWND child;
383 POINT pt;
384
385 TRACE("(%p)->(%d %d %p)\n", This, xLeft, yTop, pvarID);
386
387 V_VT(pvarID) = VT_I4;
388 V_I4(pvarID) = 0;
389
390 pt.x = xLeft;
391 pt.y = yTop;
392 if(!IsWindowVisible(This->hwnd) || !ScreenToClient(This->hwnd, &pt))
393 return S_OK;
394
395 child = ChildWindowFromPointEx(This->hwnd, pt, CWP_SKIPINVISIBLE);
396 if(!child || child==This->hwnd)
397 return S_OK;
398
399 V_VT(pvarID) = VT_DISPATCH;
400 return AccessibleObjectFromWindow(child, OBJID_WINDOW,
401 &IID_IDispatch, (void**)&V_DISPATCH(pvarID));
402 }
403
404 static HRESULT WINAPI Client_accDoDefaultAction(IAccessible *iface, VARIANT varID)
405 {
406 Client *This = impl_from_Client(iface);
407 FIXME("(%p)->(%s)\n", This, debugstr_variant(&varID));
408 return E_NOTIMPL;
409 }
410
411 static HRESULT WINAPI Client_put_accName(IAccessible *iface, VARIANT varID, BSTR pszName)
412 {
413 Client *This = impl_from_Client(iface);
414 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszName));
415 return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI Client_put_accValue(IAccessible *iface, VARIANT varID, BSTR pszValue)
419 {
420 Client *This = impl_from_Client(iface);
421 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszValue));
422 return E_NOTIMPL;
423 }
424
425 static const IAccessibleVtbl ClientVtbl = {
426 Client_QueryInterface,
427 Client_AddRef,
428 Client_Release,
429 Client_GetTypeInfoCount,
430 Client_GetTypeInfo,
431 Client_GetIDsOfNames,
432 Client_Invoke,
433 Client_get_accParent,
434 Client_get_accChildCount,
435 Client_get_accChild,
436 Client_get_accName,
437 Client_get_accValue,
438 Client_get_accDescription,
439 Client_get_accRole,
440 Client_get_accState,
441 Client_get_accHelp,
442 Client_get_accHelpTopic,
443 Client_get_accKeyboardShortcut,
444 Client_get_accFocus,
445 Client_get_accSelection,
446 Client_get_accDefaultAction,
447 Client_accSelect,
448 Client_accLocation,
449 Client_accNavigate,
450 Client_accHitTest,
451 Client_accDoDefaultAction,
452 Client_put_accName,
453 Client_put_accValue
454 };
455
456 static inline Client* impl_from_Client_OleWindow(IOleWindow *iface)
457 {
458 return CONTAINING_RECORD(iface, Client, IOleWindow_iface);
459 }
460
461 static HRESULT WINAPI Client_OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **ppv)
462 {
463 Client *This = impl_from_Client_OleWindow(iface);
464 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
465 }
466
467 static ULONG WINAPI Client_OleWindow_AddRef(IOleWindow *iface)
468 {
469 Client *This = impl_from_Client_OleWindow(iface);
470 return IAccessible_AddRef(&This->IAccessible_iface);
471 }
472
473 static ULONG WINAPI Client_OleWindow_Release(IOleWindow *iface)
474 {
475 Client *This = impl_from_Client_OleWindow(iface);
476 return IAccessible_Release(&This->IAccessible_iface);
477 }
478
479 static HRESULT WINAPI Client_OleWindow_GetWindow(IOleWindow *iface, HWND *phwnd)
480 {
481 Client *This = impl_from_Client_OleWindow(iface);
482
483 TRACE("(%p)->(%p)\n", This, phwnd);
484
485 *phwnd = This->hwnd;
486 return S_OK;
487 }
488
489 static HRESULT WINAPI Client_OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMode)
490 {
491 Client *This = impl_from_Client_OleWindow(iface);
492 FIXME("(%p)->(%x)\n", This, fEnterMode);
493 return E_NOTIMPL;
494 }
495
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
502 };
503
504 static inline Client* impl_from_Client_EnumVARIANT(IEnumVARIANT *iface)
505 {
506 return CONTAINING_RECORD(iface, Client, IEnumVARIANT_iface);
507 }
508
509 static HRESULT WINAPI Client_EnumVARIANT_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
510 {
511 Client *This = impl_from_Client_EnumVARIANT(iface);
512 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
513 }
514
515 static ULONG WINAPI Client_EnumVARIANT_AddRef(IEnumVARIANT *iface)
516 {
517 Client *This = impl_from_Client_EnumVARIANT(iface);
518 return IAccessible_AddRef(&This->IAccessible_iface);
519 }
520
521 static ULONG WINAPI Client_EnumVARIANT_Release(IEnumVARIANT *iface)
522 {
523 Client *This = impl_from_Client_EnumVARIANT(iface);
524 return IAccessible_Release(&This->IAccessible_iface);
525 }
526
527 static HRESULT WINAPI Client_EnumVARIANT_Next(IEnumVARIANT *iface,
528 ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
529 {
530 Client *This = impl_from_Client_EnumVARIANT(iface);
531 HWND cur = This->enum_pos, next;
532 ULONG fetched = 0;
533 HRESULT hr;
534
535 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
536
537 if(!celt) {
538 if(pCeltFetched)
539 *pCeltFetched = 0;
540 return S_OK;
541 }
542
543 if(!This->enum_pos)
544 next = GetWindow(This->hwnd, GW_CHILD);
545 else
546 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
547
548 while(next) {
549 cur = next;
550
551 V_VT(rgVar+fetched) = VT_DISPATCH;
552 hr = AccessibleObjectFromWindow(cur, OBJID_WINDOW,
553 &IID_IDispatch, (void**)&V_DISPATCH(rgVar+fetched));
554 if(FAILED(hr)) {
555 V_VT(rgVar+fetched) = VT_EMPTY;
556 while(fetched > 0) {
557 VariantClear(rgVar+fetched-1);
558 fetched--;
559 }
560 if(pCeltFetched)
561 *pCeltFetched = 0;
562 return hr;
563 }
564 fetched++;
565 if(fetched == celt)
566 break;
567
568 next = GetWindow(cur, GW_HWNDNEXT);
569 }
570
571 This->enum_pos = cur;
572 if(pCeltFetched)
573 *pCeltFetched = fetched;
574 return celt == fetched ? S_OK : S_FALSE;
575 }
576
577 static HRESULT WINAPI Client_EnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt)
578 {
579 Client *This = impl_from_Client_EnumVARIANT(iface);
580 HWND next;
581
582 TRACE("(%p)->(%u)\n", This, celt);
583
584 while(celt) {
585 if(!This->enum_pos)
586 next = GetWindow(This->hwnd, GW_CHILD);
587 else
588 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
589 if(!next)
590 return S_FALSE;
591
592 This->enum_pos = next;
593 celt--;
594 }
595
596 return S_OK;
597 }
598
599 static HRESULT WINAPI Client_EnumVARIANT_Reset(IEnumVARIANT *iface)
600 {
601 Client *This = impl_from_Client_EnumVARIANT(iface);
602
603 TRACE("(%p)\n", This);
604
605 This->enum_pos = 0;
606 return S_OK;
607 }
608
609 static HRESULT WINAPI Client_EnumVARIANT_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
610 {
611 Client *This = impl_from_Client_EnumVARIANT(iface);
612 FIXME("(%p)->(%p)\n", This, ppEnum);
613 return E_NOTIMPL;
614 }
615
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
624 };
625
626 HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj)
627 {
628 Client *client;
629 HRESULT hres;
630
631 if(!IsWindow(hwnd))
632 return E_FAIL;
633
634 client = heap_alloc_zero(sizeof(Client));
635 if(!client)
636 return E_OUTOFMEMORY;
637
638 client->IAccessible_iface.lpVtbl = &ClientVtbl;
639 client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl;
640 client->IEnumVARIANT_iface.lpVtbl = &ClientEnumVARIANTVtbl;
641 client->ref = 1;
642 client->hwnd = hwnd;
643 client->enum_pos = 0;
644
645 hres = IAccessible_QueryInterface(&client->IAccessible_iface, iid, obj);
646 IAccessible_Release(&client->IAccessible_iface);
647 return hres;
648 }