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