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, sizeof(name)/sizeof(WCHAR), (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, sizeof(name)/sizeof(WCHAR), (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 } 649