/* * Implementation of the OLEACC dll * * Copyright 2003 Mike McCormack 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 #include "windef.h" #include "winbase.h" #include "ole2.h" #include "commctrl.h" #include "rpcproxy.h" #include "initguid.h" #include "oleacc_private.h" #include "resource.h" #include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(oleacc); static const WCHAR lresult_atom_prefix[] = {'w','i','n','e','_','o','l','e','a','c','c',':'}; static const WCHAR menuW[] = {'#','3','2','7','6','8',0}; static const WCHAR desktopW[] = {'#','3','2','7','6','9',0}; static const WCHAR dialogW[] = {'#','3','2','7','7','0',0}; static const WCHAR winswitchW[] = {'#','3','2','7','7','1',0}; static const WCHAR mdi_clientW[] = {'M','D','I','C','l','i','e','n','t',0}; static const WCHAR richeditW[] = {'R','I','C','H','E','D','I','T',0}; static const WCHAR richedit20aW[] = {'R','i','c','h','E','d','i','t','2','0','A',0}; static const WCHAR richedit20wW[] = {'R','i','c','h','E','d','i','t','2','0','W',0}; typedef HRESULT (WINAPI *accessible_create)(HWND, const IID*, void**); extern HRESULT WINAPI OLEACC_DllGetClassObject(REFCLSID, REFIID, void**) DECLSPEC_HIDDEN; extern BOOL WINAPI OLEACC_DllMain(HINSTANCE, DWORD, void*) DECLSPEC_HIDDEN; extern HRESULT WINAPI OLEACC_DllRegisterServer(void) DECLSPEC_HIDDEN; extern HRESULT WINAPI OLEACC_DllUnregisterServer(void) DECLSPEC_HIDDEN; static struct { const WCHAR *name; DWORD idx; accessible_create create_client; accessible_create create_window; } builtin_classes[] = { {WC_LISTBOXW, 0x10000, NULL, NULL}, {menuW, 0x10001, NULL, NULL}, {WC_BUTTONW, 0x10002, NULL, NULL}, {WC_STATICW, 0x10003, NULL, NULL}, {WC_EDITW, 0x10004, NULL, NULL}, {WC_COMBOBOXW, 0x10005, NULL, NULL}, {dialogW, 0x10006, NULL, NULL}, {winswitchW, 0x10007, NULL, NULL}, {mdi_clientW, 0x10008, NULL, NULL}, {desktopW, 0x10009, NULL, NULL}, {WC_SCROLLBARW, 0x1000a, NULL, NULL}, {STATUSCLASSNAMEW, 0x1000b, NULL, NULL}, {TOOLBARCLASSNAMEW, 0x1000c, NULL, NULL}, {PROGRESS_CLASSW, 0x1000d, NULL, NULL}, {ANIMATE_CLASSW, 0x1000e, NULL, NULL}, {WC_TABCONTROLW, 0x1000f, NULL, NULL}, {HOTKEY_CLASSW, 0x10010, NULL, NULL}, {WC_HEADERW, 0x10011, NULL, NULL}, {TRACKBAR_CLASSW, 0x10012, NULL, NULL}, {WC_LISTVIEWW, 0x10013, NULL, NULL}, {UPDOWN_CLASSW, 0x10016, NULL, NULL}, {TOOLTIPS_CLASSW, 0x10018, NULL, NULL}, {WC_TREEVIEWW, 0x10019, NULL, NULL}, {MONTHCAL_CLASSW, 0, NULL, NULL}, {DATETIMEPICK_CLASSW, 0, NULL, NULL}, {WC_IPADDRESSW, 0, NULL, NULL}, {richeditW, 0x1001c, NULL, NULL}, {richedit20aW, 0, NULL, NULL}, {richedit20wW, 0, NULL, NULL}, }; static HINSTANCE oleacc_handle = 0; int convert_child_id(VARIANT *v) { switch(V_VT(v)) { case VT_I4: return V_I4(v); default: FIXME("unhandled child ID variant type: %d\n", V_VT(v)); return -1; } } static accessible_create get_builtin_accessible_obj(HWND hwnd, LONG objid) { WCHAR class_name[64]; int i, idx; if(!RealGetWindowClassW(hwnd, class_name, ARRAY_SIZE(class_name))) return NULL; TRACE("got window class: %s\n", debugstr_w(class_name)); for(i=0; i 0)){ if(rolemax > 0) lpRole[0] = '\0'; return 0; } return ret; } UINT WINAPI GetRoleTextA(DWORD role, LPSTR lpRole, UINT rolemax) { UINT length; WCHAR *roletextW; TRACE("%u %p %u\n", role, lpRole, rolemax); if(lpRole && !rolemax) return 0; length = GetRoleTextW(role, NULL, 0); if(!length) { if(lpRole && rolemax) lpRole[0] = 0; return 0; } roletextW = HeapAlloc(GetProcessHeap(), 0, (length + 1)*sizeof(WCHAR)); if(!roletextW) return 0; GetRoleTextW(role, roletextW, length + 1); length = WideCharToMultiByte( CP_ACP, 0, roletextW, -1, NULL, 0, NULL, NULL ); if(!lpRole){ HeapFree(GetProcessHeap(), 0, roletextW); return length - 1; } if(rolemax < length) { HeapFree(GetProcessHeap(), 0, roletextW); lpRole[0] = 0; return 0; } WideCharToMultiByte( CP_ACP, 0, roletextW, -1, lpRole, rolemax, NULL, NULL ); if(rolemax < length){ lpRole[rolemax-1] = '\0'; length = rolemax; } HeapFree(GetProcessHeap(), 0, roletextW); return length - 1; } UINT WINAPI GetStateTextW(DWORD state_bit, WCHAR *state_str, UINT state_str_len) { DWORD state_id; TRACE("%x %p %u\n", state_bit, state_str, state_str_len); if(state_bit & ~(STATE_SYSTEM_VALID | STATE_SYSTEM_HASPOPUP)) { if(state_str && state_str_len) state_str[0] = 0; return 0; } state_id = IDS_STATE_NORMAL; while(state_bit) { state_id++; state_bit /= 2; } if(state_str) { UINT ret = LoadStringW(oleacc_handle, state_id, state_str, state_str_len); if(!ret && state_str_len) state_str[0] = 0; return ret; }else { WCHAR *tmp; return LoadStringW(oleacc_handle, state_id, (WCHAR*)&tmp, 0); } } UINT WINAPI GetStateTextA(DWORD state_bit, CHAR *state_str, UINT state_str_len) { DWORD state_id; TRACE("%x %p %u\n", state_bit, state_str, state_str_len); if(state_str && !state_str_len) return 0; if(state_bit & ~(STATE_SYSTEM_VALID | STATE_SYSTEM_HASPOPUP)) { if(state_str && state_str_len) state_str[0] = 0; return 0; } state_id = IDS_STATE_NORMAL; while(state_bit) { state_id++; state_bit /= 2; } if(state_str) { UINT ret = LoadStringA(oleacc_handle, state_id, state_str, state_str_len); if(!ret && state_str_len) state_str[0] = 0; return ret; }else { CHAR tmp[256]; return LoadStringA(oleacc_handle, state_id, tmp, sizeof(tmp)); } } HRESULT WINAPI AccessibleChildren(IAccessible *container, LONG start, LONG count, VARIANT *children, LONG *children_cnt) { IEnumVARIANT *ev; LONG i, child_no; HRESULT hr; TRACE("%p %d %d %p %p\n", container, start, count, children, children_cnt); if(!container || !children || !children_cnt) return E_INVALIDARG; for(i=0; i