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 39 static inline Client* impl_from_Client(IAccessible *iface) 40 { 41 return CONTAINING_RECORD(iface, Client, IAccessible_iface); 42 } 43 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 455 static inline Client* impl_from_Client_OleWindow(IOleWindow *iface) 456 { 457 return CONTAINING_RECORD(iface, Client, IOleWindow_iface); 458 } 459 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 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 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 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 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 503 static inline Client* impl_from_Client_EnumVARIANT(IEnumVARIANT *iface) 504 { 505 return CONTAINING_RECORD(iface, Client, IEnumVARIANT_iface); 506 } 507 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 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 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 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 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 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 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 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