| /* |
| * Copyright 2014 Piotr Caban for CodeWeavers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #define COBJMACROS |
| |
| #include "oleacc_private.h" |
| |
| #include "wine/unicode.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(oleacc); |
| |
| typedef struct { |
| IAccessible IAccessible_iface; |
| IOleWindow IOleWindow_iface; |
| IEnumVARIANT IEnumVARIANT_iface; |
| |
| LONG ref; |
| |
| HWND hwnd; |
| HWND enum_pos; |
| } Client; |
| |
| static inline Client* impl_from_Client(IAccessible *iface) |
| { |
| return CONTAINING_RECORD(iface, Client, IAccessible_iface); |
| } |
| |
| static HRESULT WINAPI Client_QueryInterface(IAccessible *iface, REFIID riid, void **ppv) |
| { |
| Client *This = impl_from_Client(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); |
| |
| if(IsEqualIID(riid, &IID_IAccessible) || |
| IsEqualIID(riid, &IID_IDispatch) || |
| IsEqualIID(riid, &IID_IUnknown)) { |
| *ppv = iface; |
| }else if(IsEqualIID(riid, &IID_IOleWindow)) { |
| *ppv = &This->IOleWindow_iface; |
| }else if(IsEqualIID(riid, &IID_IEnumVARIANT)) { |
| *ppv = &This->IEnumVARIANT_iface; |
| }else { |
| WARN("no interface: %s\n", debugstr_guid(riid)); |
| *ppv = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| IAccessible_AddRef(iface); |
| return S_OK; |
| } |
| |
| static ULONG WINAPI Client_AddRef(IAccessible *iface) |
| { |
| Client *This = impl_from_Client(iface); |
| ULONG ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p) ref = %u\n", This, ref); |
| return ref; |
| } |
| |
| static ULONG WINAPI Client_Release(IAccessible *iface) |
| { |
| Client *This = impl_from_Client(iface); |
| ULONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p) ref = %u\n", This, ref); |
| |
| if(!ref) |
| heap_free(This); |
| return ref; |
| } |
| |
| static HRESULT WINAPI Client_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%p)\n", This, pctinfo); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_GetTypeInfo(IAccessible *iface, |
| UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%u %x %p)\n", This, iTInfo, lcid, ppTInfo); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_GetIDsOfNames(IAccessible *iface, REFIID riid, |
| LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%s %p %u %x %p)\n", This, debugstr_guid(riid), |
| rgszNames, cNames, lcid, rgDispId); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_Invoke(IAccessible *iface, DISPID dispIdMember, |
| REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, |
| VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%x %s %x %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), |
| lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_get_accParent(IAccessible *iface, IDispatch **ppdispParent) |
| { |
| Client *This = impl_from_Client(iface); |
| |
| TRACE("(%p)->(%p)\n", This, ppdispParent); |
| |
| return AccessibleObjectFromWindow(This->hwnd, OBJID_WINDOW, |
| &IID_IDispatch, (void**)ppdispParent); |
| } |
| |
| static HRESULT WINAPI Client_get_accChildCount(IAccessible *iface, LONG *pcountChildren) |
| { |
| Client *This = impl_from_Client(iface); |
| HWND cur; |
| |
| TRACE("(%p)->(%p)\n", This, pcountChildren); |
| |
| *pcountChildren = 0; |
| for(cur = GetWindow(This->hwnd, GW_CHILD); cur; cur = GetWindow(cur, GW_HWNDNEXT)) |
| (*pcountChildren)++; |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Client_get_accChild(IAccessible *iface, |
| VARIANT varChildID, IDispatch **ppdispChild) |
| { |
| Client *This = impl_from_Client(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varChildID), ppdispChild); |
| |
| *ppdispChild = NULL; |
| return E_INVALIDARG; |
| } |
| |
| static HRESULT WINAPI Client_get_accName(IAccessible *iface, VARIANT varID, BSTR *pszName) |
| { |
| Client *This = impl_from_Client(iface); |
| WCHAR name[1024]; |
| UINT i, len; |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszName); |
| |
| *pszName = NULL; |
| if(convert_child_id(&varID) != CHILDID_SELF || !IsWindow(This->hwnd)) |
| return E_INVALIDARG; |
| |
| len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name); |
| if(!len) |
| return S_FALSE; |
| |
| for(i=0; i<len; i++) { |
| if(name[i] == '&') { |
| len--; |
| memmove(name+i, name+i+1, (len-i)*sizeof(WCHAR)); |
| break; |
| } |
| } |
| |
| *pszName = SysAllocStringLen(name, len); |
| return *pszName ? S_OK : E_OUTOFMEMORY; |
| } |
| |
| static HRESULT WINAPI Client_get_accValue(IAccessible *iface, VARIANT varID, BSTR *pszValue) |
| { |
| Client *This = impl_from_Client(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszValue); |
| |
| *pszValue = NULL; |
| if(convert_child_id(&varID) != CHILDID_SELF) |
| return E_INVALIDARG; |
| return S_FALSE; |
| } |
| |
| static HRESULT WINAPI Client_get_accDescription(IAccessible *iface, |
| VARIANT varID, BSTR *pszDescription) |
| { |
| Client *This = impl_from_Client(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDescription); |
| |
| *pszDescription = NULL; |
| if(convert_child_id(&varID) != CHILDID_SELF) |
| return E_INVALIDARG; |
| return S_FALSE; |
| } |
| |
| static HRESULT WINAPI Client_get_accRole(IAccessible *iface, VARIANT varID, VARIANT *pvarRole) |
| { |
| Client *This = impl_from_Client(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarRole); |
| |
| if(convert_child_id(&varID) != CHILDID_SELF) { |
| V_VT(pvarRole) = VT_EMPTY; |
| return E_INVALIDARG; |
| } |
| |
| V_VT(pvarRole) = VT_I4; |
| V_I4(pvarRole) = ROLE_SYSTEM_CLIENT; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Client_get_accState(IAccessible *iface, VARIANT varID, VARIANT *pvarState) |
| { |
| Client *This = impl_from_Client(iface); |
| LONG style; |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarState); |
| |
| if(convert_child_id(&varID) != CHILDID_SELF) { |
| V_VT(pvarState) = VT_EMPTY; |
| return E_INVALIDARG; |
| } |
| |
| V_VT(pvarState) = VT_I4; |
| V_I4(pvarState) = 0; |
| |
| style = GetWindowLongW(This->hwnd, GWL_STYLE); |
| if(style & WS_DISABLED) |
| V_I4(pvarState) |= STATE_SYSTEM_UNAVAILABLE; |
| else if(IsWindow(This->hwnd)) |
| V_I4(pvarState) |= STATE_SYSTEM_FOCUSABLE; |
| if(GetFocus() == This->hwnd) |
| V_I4(pvarState) |= STATE_SYSTEM_FOCUSED; |
| if(!(style & WS_VISIBLE)) |
| V_I4(pvarState) |= STATE_SYSTEM_INVISIBLE; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Client_get_accHelp(IAccessible *iface, VARIANT varID, BSTR *pszHelp) |
| { |
| Client *This = impl_from_Client(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszHelp); |
| |
| *pszHelp = NULL; |
| if(convert_child_id(&varID) != CHILDID_SELF) |
| return E_INVALIDARG; |
| return S_FALSE; |
| } |
| |
| static HRESULT WINAPI Client_get_accHelpTopic(IAccessible *iface, |
| BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%p %s %p)\n", This, pszHelpFile, debugstr_variant(&varID), pidTopic); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_get_accKeyboardShortcut(IAccessible *iface, |
| VARIANT varID, BSTR *pszKeyboardShortcut) |
| { |
| static const WCHAR shortcut_fmt[] = {'A','l','t','+','!',0}; |
| Client *This = impl_from_Client(iface); |
| WCHAR name[1024]; |
| UINT i, len; |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszKeyboardShortcut); |
| |
| *pszKeyboardShortcut = NULL; |
| if(convert_child_id(&varID) != CHILDID_SELF) |
| return E_INVALIDARG; |
| |
| len = SendMessageW(This->hwnd, WM_GETTEXT, sizeof(name)/sizeof(WCHAR), (LPARAM)name); |
| for(i=0; i<len; i++) { |
| if(name[i] == '&') |
| break; |
| } |
| if(i+1 >= len) |
| return S_FALSE; |
| |
| *pszKeyboardShortcut = SysAllocString(shortcut_fmt); |
| if(!*pszKeyboardShortcut) |
| return E_OUTOFMEMORY; |
| |
| (*pszKeyboardShortcut)[4] = name[i+1]; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *pvarID) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%p)\n", This, pvarID); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_get_accSelection(IAccessible *iface, VARIANT *pvarID) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%p)\n", This, pvarID); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_get_accDefaultAction(IAccessible *iface, |
| VARIANT varID, BSTR *pszDefaultAction) |
| { |
| Client *This = impl_from_Client(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDefaultAction); |
| |
| *pszDefaultAction = NULL; |
| if(convert_child_id(&varID) != CHILDID_SELF) |
| return E_INVALIDARG; |
| return S_FALSE; |
| } |
| |
| static HRESULT WINAPI Client_accSelect(IAccessible *iface, LONG flagsSelect, VARIANT varID) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%x %s)\n", This, flagsSelect, debugstr_variant(&varID)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_accLocation(IAccessible *iface, LONG *pxLeft, |
| LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID) |
| { |
| Client *This = impl_from_Client(iface); |
| RECT rect; |
| POINT pt; |
| |
| TRACE("(%p)->(%p %p %p %p %s)\n", This, pxLeft, pyTop, |
| pcxWidth, pcyHeight, debugstr_variant(&varID)); |
| |
| *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0; |
| if(convert_child_id(&varID) != CHILDID_SELF) |
| return E_INVALIDARG; |
| |
| if(!GetClientRect(This->hwnd, &rect)) |
| return S_OK; |
| |
| pt.x = rect.left, |
| pt.y = rect.top; |
| MapWindowPoints(This->hwnd, NULL, &pt, 1); |
| *pxLeft = pt.x; |
| *pyTop = pt.y; |
| |
| pt.x = rect.right; |
| pt.y = rect.bottom; |
| MapWindowPoints(This->hwnd, NULL, &pt, 1); |
| *pcxWidth = pt.x - *pxLeft; |
| *pcyHeight = pt.y - *pyTop; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Client_accNavigate(IAccessible *iface, |
| LONG navDir, VARIANT varStart, VARIANT *pvarEnd) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%d %s %p)\n", This, navDir, debugstr_variant(&varStart), pvarEnd); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_accHitTest(IAccessible *iface, |
| LONG xLeft, LONG yTop, VARIANT *pvarID) |
| { |
| Client *This = impl_from_Client(iface); |
| HWND child; |
| POINT pt; |
| |
| TRACE("(%p)->(%d %d %p)\n", This, xLeft, yTop, pvarID); |
| |
| V_VT(pvarID) = VT_I4; |
| V_I4(pvarID) = 0; |
| |
| pt.x = xLeft; |
| pt.y = yTop; |
| if(!IsWindowVisible(This->hwnd) || !ScreenToClient(This->hwnd, &pt)) |
| return S_OK; |
| |
| child = ChildWindowFromPointEx(This->hwnd, pt, CWP_SKIPINVISIBLE); |
| if(!child || child==This->hwnd) |
| return S_OK; |
| |
| V_VT(pvarID) = VT_DISPATCH; |
| return AccessibleObjectFromWindow(child, OBJID_WINDOW, |
| &IID_IDispatch, (void**)&V_DISPATCH(pvarID)); |
| } |
| |
| static HRESULT WINAPI Client_accDoDefaultAction(IAccessible *iface, VARIANT varID) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%s)\n", This, debugstr_variant(&varID)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_put_accName(IAccessible *iface, VARIANT varID, BSTR pszName) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszName)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI Client_put_accValue(IAccessible *iface, VARIANT varID, BSTR pszValue) |
| { |
| Client *This = impl_from_Client(iface); |
| FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszValue)); |
| return E_NOTIMPL; |
| } |
| |
| static const IAccessibleVtbl ClientVtbl = { |
| Client_QueryInterface, |
| Client_AddRef, |
| Client_Release, |
| Client_GetTypeInfoCount, |
| Client_GetTypeInfo, |
| Client_GetIDsOfNames, |
| Client_Invoke, |
| Client_get_accParent, |
| Client_get_accChildCount, |
| Client_get_accChild, |
| Client_get_accName, |
| Client_get_accValue, |
| Client_get_accDescription, |
| Client_get_accRole, |
| Client_get_accState, |
| Client_get_accHelp, |
| Client_get_accHelpTopic, |
| Client_get_accKeyboardShortcut, |
| Client_get_accFocus, |
| Client_get_accSelection, |
| Client_get_accDefaultAction, |
| Client_accSelect, |
| Client_accLocation, |
| Client_accNavigate, |
| Client_accHitTest, |
| Client_accDoDefaultAction, |
| Client_put_accName, |
| Client_put_accValue |
| }; |
| |
| static inline Client* impl_from_Client_OleWindow(IOleWindow *iface) |
| { |
| return CONTAINING_RECORD(iface, Client, IOleWindow_iface); |
| } |
| |
| static HRESULT WINAPI Client_OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **ppv) |
| { |
| Client *This = impl_from_Client_OleWindow(iface); |
| return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv); |
| } |
| |
| static ULONG WINAPI Client_OleWindow_AddRef(IOleWindow *iface) |
| { |
| Client *This = impl_from_Client_OleWindow(iface); |
| return IAccessible_AddRef(&This->IAccessible_iface); |
| } |
| |
| static ULONG WINAPI Client_OleWindow_Release(IOleWindow *iface) |
| { |
| Client *This = impl_from_Client_OleWindow(iface); |
| return IAccessible_Release(&This->IAccessible_iface); |
| } |
| |
| static HRESULT WINAPI Client_OleWindow_GetWindow(IOleWindow *iface, HWND *phwnd) |
| { |
| Client *This = impl_from_Client_OleWindow(iface); |
| |
| TRACE("(%p)->(%p)\n", This, phwnd); |
| |
| *phwnd = This->hwnd; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Client_OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMode) |
| { |
| Client *This = impl_from_Client_OleWindow(iface); |
| FIXME("(%p)->(%x)\n", This, fEnterMode); |
| return E_NOTIMPL; |
| } |
| |
| static const IOleWindowVtbl ClientOleWindowVtbl = { |
| Client_OleWindow_QueryInterface, |
| Client_OleWindow_AddRef, |
| Client_OleWindow_Release, |
| Client_OleWindow_GetWindow, |
| Client_OleWindow_ContextSensitiveHelp |
| }; |
| |
| static inline Client* impl_from_Client_EnumVARIANT(IEnumVARIANT *iface) |
| { |
| return CONTAINING_RECORD(iface, Client, IEnumVARIANT_iface); |
| } |
| |
| static HRESULT WINAPI Client_EnumVARIANT_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) |
| { |
| Client *This = impl_from_Client_EnumVARIANT(iface); |
| return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv); |
| } |
| |
| static ULONG WINAPI Client_EnumVARIANT_AddRef(IEnumVARIANT *iface) |
| { |
| Client *This = impl_from_Client_EnumVARIANT(iface); |
| return IAccessible_AddRef(&This->IAccessible_iface); |
| } |
| |
| static ULONG WINAPI Client_EnumVARIANT_Release(IEnumVARIANT *iface) |
| { |
| Client *This = impl_from_Client_EnumVARIANT(iface); |
| return IAccessible_Release(&This->IAccessible_iface); |
| } |
| |
| static HRESULT WINAPI Client_EnumVARIANT_Next(IEnumVARIANT *iface, |
| ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) |
| { |
| Client *This = impl_from_Client_EnumVARIANT(iface); |
| HWND cur = This->enum_pos, next; |
| ULONG fetched = 0; |
| HRESULT hr; |
| |
| TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched); |
| |
| if(!celt) { |
| if(pCeltFetched) |
| *pCeltFetched = 0; |
| return S_OK; |
| } |
| |
| if(!This->enum_pos) |
| next = GetWindow(This->hwnd, GW_CHILD); |
| else |
| next = GetWindow(This->enum_pos, GW_HWNDNEXT); |
| |
| while(next) { |
| cur = next; |
| |
| V_VT(rgVar+fetched) = VT_DISPATCH; |
| hr = AccessibleObjectFromWindow(cur, OBJID_WINDOW, |
| &IID_IDispatch, (void**)&V_DISPATCH(rgVar+fetched)); |
| if(FAILED(hr)) { |
| V_VT(rgVar+fetched) = VT_EMPTY; |
| while(fetched > 0) { |
| VariantClear(rgVar+fetched-1); |
| fetched--; |
| } |
| if(pCeltFetched) |
| *pCeltFetched = 0; |
| return hr; |
| } |
| fetched++; |
| if(fetched == celt) |
| break; |
| |
| next = GetWindow(cur, GW_HWNDNEXT); |
| } |
| |
| This->enum_pos = cur; |
| if(pCeltFetched) |
| *pCeltFetched = fetched; |
| return celt == fetched ? S_OK : S_FALSE; |
| } |
| |
| static HRESULT WINAPI Client_EnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt) |
| { |
| Client *This = impl_from_Client_EnumVARIANT(iface); |
| HWND next; |
| |
| TRACE("(%p)->(%u)\n", This, celt); |
| |
| while(celt) { |
| if(!This->enum_pos) |
| next = GetWindow(This->hwnd, GW_CHILD); |
| else |
| next = GetWindow(This->enum_pos, GW_HWNDNEXT); |
| if(!next) |
| return S_FALSE; |
| |
| This->enum_pos = next; |
| celt--; |
| } |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Client_EnumVARIANT_Reset(IEnumVARIANT *iface) |
| { |
| Client *This = impl_from_Client_EnumVARIANT(iface); |
| |
| TRACE("(%p)\n", This); |
| |
| This->enum_pos = 0; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Client_EnumVARIANT_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) |
| { |
| Client *This = impl_from_Client_EnumVARIANT(iface); |
| FIXME("(%p)->(%p)\n", This, ppEnum); |
| return E_NOTIMPL; |
| } |
| |
| static const IEnumVARIANTVtbl ClientEnumVARIANTVtbl = { |
| Client_EnumVARIANT_QueryInterface, |
| Client_EnumVARIANT_AddRef, |
| Client_EnumVARIANT_Release, |
| Client_EnumVARIANT_Next, |
| Client_EnumVARIANT_Skip, |
| Client_EnumVARIANT_Reset, |
| Client_EnumVARIANT_Clone |
| }; |
| |
| HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj) |
| { |
| Client *client; |
| HRESULT hres; |
| |
| if(!IsWindow(hwnd)) |
| return E_FAIL; |
| |
| client = heap_alloc_zero(sizeof(Client)); |
| if(!client) |
| return E_OUTOFMEMORY; |
| |
| client->IAccessible_iface.lpVtbl = &ClientVtbl; |
| client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl; |
| client->IEnumVARIANT_iface.lpVtbl = &ClientEnumVARIANTVtbl; |
| client->ref = 1; |
| client->hwnd = hwnd; |
| client->enum_pos = 0; |
| |
| hres = IAccessible_QueryInterface(&client->IAccessible_iface, iid, obj); |
| IAccessible_Release(&client->IAccessible_iface); |
| return hres; |
| } |