dwrite: Implement CreateFontFaceFromHdc().
[wine.git] / dlls / oleacc / main.c
blobe5fe6cdb406384a4e096cf8bb78d8a5ce5f7b138
1 /*
2 * Implementation of the OLEACC dll
4 * Copyright 2003 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "ole2.h"
27 #include "commctrl.h"
28 #include "rpcproxy.h"
30 #include "initguid.h"
31 #include "oleacc_private.h"
32 #include "resource.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
39 static const WCHAR lresult_atom_prefix[] = {'w','i','n','e','_','o','l','e','a','c','c',':'};
41 static const WCHAR menuW[] = {'#','3','2','7','6','8',0};
42 static const WCHAR desktopW[] = {'#','3','2','7','6','9',0};
43 static const WCHAR dialogW[] = {'#','3','2','7','7','0',0};
44 static const WCHAR winswitchW[] = {'#','3','2','7','7','1',0};
45 static const WCHAR mdi_clientW[] = {'M','D','I','C','l','i','e','n','t',0};
46 static const WCHAR richeditW[] = {'R','I','C','H','E','D','I','T',0};
47 static const WCHAR richedit20aW[] = {'R','i','c','h','E','d','i','t','2','0','A',0};
48 static const WCHAR richedit20wW[] = {'R','i','c','h','E','d','i','t','2','0','W',0};
50 typedef HRESULT (WINAPI *accessible_create)(HWND, const IID*, void**);
52 static struct {
53 const WCHAR *name;
54 DWORD idx;
55 accessible_create create_client;
56 accessible_create create_window;
57 } builtin_classes[] = {
58 {WC_LISTBOXW, 0x10000, NULL, NULL},
59 {menuW, 0x10001, NULL, NULL},
60 {WC_BUTTONW, 0x10002, NULL, NULL},
61 {WC_STATICW, 0x10003, NULL, NULL},
62 {WC_EDITW, 0x10004, NULL, NULL},
63 {WC_COMBOBOXW, 0x10005, NULL, NULL},
64 {dialogW, 0x10006, NULL, NULL},
65 {winswitchW, 0x10007, NULL, NULL},
66 {mdi_clientW, 0x10008, NULL, NULL},
67 {desktopW, 0x10009, NULL, NULL},
68 {WC_SCROLLBARW, 0x1000a, NULL, NULL},
69 {STATUSCLASSNAMEW, 0x1000b, NULL, NULL},
70 {TOOLBARCLASSNAMEW, 0x1000c, NULL, NULL},
71 {PROGRESS_CLASSW, 0x1000d, NULL, NULL},
72 {ANIMATE_CLASSW, 0x1000e, NULL, NULL},
73 {WC_TABCONTROLW, 0x1000f, NULL, NULL},
74 {HOTKEY_CLASSW, 0x10010, NULL, NULL},
75 {WC_HEADERW, 0x10011, NULL, NULL},
76 {TRACKBAR_CLASSW, 0x10012, NULL, NULL},
77 {WC_LISTVIEWW, 0x10013, NULL, NULL},
78 {UPDOWN_CLASSW, 0x10016, NULL, NULL},
79 {TOOLTIPS_CLASSW, 0x10018, NULL, NULL},
80 {WC_TREEVIEWW, 0x10019, NULL, NULL},
81 {MONTHCAL_CLASSW, 0, NULL, NULL},
82 {DATETIMEPICK_CLASSW, 0, NULL, NULL},
83 {WC_IPADDRESSW, 0, NULL, NULL},
84 {richeditW, 0x1001c, NULL, NULL},
85 {richedit20aW, 0, NULL, NULL},
86 {richedit20wW, 0, NULL, NULL},
89 static HINSTANCE oleacc_handle = 0;
91 int convert_child_id(VARIANT *v)
93 switch(V_VT(v)) {
94 case VT_I4:
95 return V_I4(v);
96 default:
97 FIXME("unhandled child ID variant type: %d\n", V_VT(v));
98 return -1;
102 static accessible_create get_builtin_accessible_obj(HWND hwnd, LONG objid)
104 WCHAR class_name[64];
105 int i, idx;
107 if(!RealGetWindowClassW(hwnd, class_name, sizeof(class_name)/sizeof(WCHAR)))
108 return NULL;
109 TRACE("got window class: %s\n", debugstr_w(class_name));
111 for(i=0; i<sizeof(builtin_classes)/sizeof(builtin_classes[0]); i++) {
112 if(!strcmpiW(class_name, builtin_classes[i].name)) {
113 accessible_create ret;
115 ret = (objid==OBJID_CLIENT ?
116 builtin_classes[i].create_client :
117 builtin_classes[i].create_window);
118 if(!ret)
119 FIXME("unhandled window class: %s\n", debugstr_w(class_name));
120 return ret;
124 idx = SendMessageW(hwnd, WM_GETOBJECT, 0, OBJID_QUERYCLASSNAMEIDX);
125 if(idx) {
126 for(i=0; i<sizeof(builtin_classes)/sizeof(builtin_classes[0]); i++) {
127 if(idx == builtin_classes[i].idx) {
128 accessible_create ret;
130 ret = (objid==OBJID_CLIENT ?
131 builtin_classes[i].create_client :
132 builtin_classes[i].create_window);
133 if(!ret)
134 FIXME("unhandled class name idx: %x\n", idx);
135 return ret;
139 WARN("unhandled class name idx: %x\n", idx);
142 return NULL;
145 HRESULT WINAPI CreateStdAccessibleObject( HWND hwnd, LONG idObject,
146 REFIID riidInterface, void** ppvObject )
148 accessible_create create;
150 TRACE("%p %d %s %p\n", hwnd, idObject,
151 debugstr_guid( riidInterface ), ppvObject );
153 switch(idObject) {
154 case OBJID_CLIENT:
155 create = get_builtin_accessible_obj(hwnd, idObject);
156 if(create) return create(hwnd, riidInterface, ppvObject);
157 return create_client_object(hwnd, riidInterface, ppvObject);
158 case OBJID_WINDOW:
159 create = get_builtin_accessible_obj(hwnd, idObject);
160 if(create) return create(hwnd, riidInterface, ppvObject);
161 return create_window_object(hwnd, riidInterface, ppvObject);
162 default:
163 FIXME("unhandled object id: %d\n", idObject);
164 return E_NOTIMPL;
168 HRESULT WINAPI ObjectFromLresult( LRESULT result, REFIID riid, WPARAM wParam, void **ppObject )
170 WCHAR atom_str[sizeof(lresult_atom_prefix)/sizeof(WCHAR)+3*8+3];
171 HANDLE server_proc, server_mapping, mapping;
172 DWORD proc_id, size;
173 IStream *stream;
174 HGLOBAL data;
175 void *view;
176 HRESULT hr;
177 WCHAR *p;
179 TRACE("%ld %s %ld %p\n", result, debugstr_guid(riid), wParam, ppObject );
181 if(wParam)
182 FIXME("unsupported wParam = %lx\n", wParam);
184 if(!ppObject)
185 return E_INVALIDARG;
186 *ppObject = NULL;
188 if(result != (ATOM)result)
189 return E_FAIL;
191 if(!GlobalGetAtomNameW(result, atom_str, sizeof(atom_str)/sizeof(WCHAR)))
192 return E_FAIL;
193 if(memcmp(atom_str, lresult_atom_prefix, sizeof(lresult_atom_prefix)))
194 return E_FAIL;
195 p = atom_str + sizeof(lresult_atom_prefix)/sizeof(WCHAR);
196 proc_id = strtoulW(p, &p, 16);
197 if(*p != ':')
198 return E_FAIL;
199 server_mapping = ULongToHandle( strtoulW(p+1, &p, 16) );
200 if(*p != ':')
201 return E_FAIL;
202 size = strtoulW(p+1, &p, 16);
203 if(*p != 0)
204 return E_FAIL;
206 server_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, proc_id);
207 if(!server_proc)
208 return E_FAIL;
210 if(!DuplicateHandle(server_proc, server_mapping, GetCurrentProcess(), &mapping,
211 0, FALSE, DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS))
212 return E_FAIL;
213 CloseHandle(server_proc);
214 GlobalDeleteAtom(result);
216 view = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
217 CloseHandle(mapping);
218 if(!view)
219 return E_FAIL;
221 data = GlobalAlloc(GMEM_FIXED, size);
222 if(!data)
223 return E_OUTOFMEMORY;
224 memcpy(data, view, size);
225 UnmapViewOfFile(view);
227 hr = CreateStreamOnHGlobal(data, TRUE, &stream);
228 if(FAILED(hr)) {
229 GlobalFree(data);
230 return hr;
233 hr = CoUnmarshalInterface(stream, riid, ppObject);
234 IStream_Release(stream);
235 return hr;
238 LRESULT WINAPI LresultFromObject( REFIID riid, WPARAM wParam, LPUNKNOWN pAcc )
240 static const WCHAR atom_fmt[] = {'%','0','8','x',':','%','0','8','x',':','%','0','8','x',0};
241 static const LARGE_INTEGER seek_zero = {{0}};
243 WCHAR atom_str[sizeof(lresult_atom_prefix)/sizeof(WCHAR)+3*8+3];
244 IStream *stream;
245 HANDLE mapping;
246 STATSTG stat;
247 HRESULT hr;
248 ATOM atom;
249 void *view;
251 TRACE("%s %ld %p\n", debugstr_guid(riid), wParam, pAcc);
253 if(wParam)
254 FIXME("unsupported wParam = %lx\n", wParam);
256 if(!pAcc)
257 return E_INVALIDARG;
259 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
260 if(FAILED(hr))
261 return hr;
263 hr = CoMarshalInterface(stream, riid, pAcc, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
264 if(FAILED(hr)) {
265 IStream_Release(stream);
266 return hr;
269 hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL);
270 if(FAILED(hr)) {
271 IStream_Release(stream);
272 return hr;
275 hr = IStream_Stat(stream, &stat, STATFLAG_NONAME);
276 if(FAILED(hr)) {
277 CoReleaseMarshalData(stream);
278 IStream_Release(stream);
279 return hr;
280 }else if(stat.cbSize.u.HighPart) {
281 FIXME("stream size to big\n");
282 CoReleaseMarshalData(stream);
283 IStream_Release(stream);
284 return E_NOTIMPL;
287 mapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
288 stat.cbSize.u.HighPart, stat.cbSize.u.LowPart, NULL);
289 if(!mapping) {
290 CoReleaseMarshalData(stream);
291 IStream_Release(stream);
292 return hr;
295 view = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
296 if(!view) {
297 CloseHandle(mapping);
298 CoReleaseMarshalData(stream);
299 IStream_Release(stream);
300 return E_FAIL;
303 hr = IStream_Read(stream, view, stat.cbSize.u.LowPart, NULL);
304 UnmapViewOfFile(view);
305 if(FAILED(hr)) {
306 CloseHandle(mapping);
307 hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL);
308 if(SUCCEEDED(hr))
309 CoReleaseMarshalData(stream);
310 IStream_Release(stream);
311 return hr;
315 memcpy(atom_str, lresult_atom_prefix, sizeof(lresult_atom_prefix));
316 sprintfW(atom_str+sizeof(lresult_atom_prefix)/sizeof(WCHAR),
317 atom_fmt, GetCurrentProcessId(), HandleToUlong(mapping), stat.cbSize.u.LowPart);
318 atom = GlobalAddAtomW(atom_str);
319 if(!atom) {
320 CloseHandle(mapping);
321 hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL);
322 if(SUCCEEDED(hr))
323 CoReleaseMarshalData(stream);
324 IStream_Release(stream);
325 return E_FAIL;
328 IStream_Release(stream);
329 return atom;
332 HRESULT WINAPI AccessibleObjectFromPoint( POINT ptScreen, IAccessible** ppacc, VARIANT* pvarChild )
334 FIXME("{%d,%d} %p %p: stub\n", ptScreen.x, ptScreen.y, ppacc, pvarChild );
335 return E_NOTIMPL;
338 HRESULT WINAPI AccessibleObjectFromWindow( HWND hwnd, DWORD dwObjectID,
339 REFIID riid, void** ppvObject )
341 TRACE("%p %d %s %p\n", hwnd, dwObjectID,
342 debugstr_guid( riid ), ppvObject );
344 if(!ppvObject)
345 return E_INVALIDARG;
346 *ppvObject = NULL;
348 if(IsWindow(hwnd)) {
349 LRESULT lres;
351 lres = SendMessageW(hwnd, WM_GETOBJECT, 0xffffffff, dwObjectID);
352 if(FAILED(lres))
353 return lres;
354 else if(lres)
355 return ObjectFromLresult(lres, riid, 0, ppvObject);
358 return CreateStdAccessibleObject(hwnd, dwObjectID, riid, ppvObject);
361 HRESULT WINAPI WindowFromAccessibleObject(IAccessible *acc, HWND *phwnd)
363 IDispatch *parent;
364 IOleWindow *ow;
365 HRESULT hres;
367 TRACE("%p %p\n", acc, phwnd);
369 IAccessible_AddRef(acc);
370 while(1) {
371 hres = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void**)&ow);
372 if(SUCCEEDED(hres)) {
373 hres = IOleWindow_GetWindow(ow, phwnd);
374 IOleWindow_Release(ow);
375 IAccessible_Release(acc);
376 return hres;
379 hres = IAccessible_get_accParent(acc, &parent);
380 IAccessible_Release(acc);
381 if(FAILED(hres))
382 return hres;
383 if(hres!=S_OK || !parent) {
384 *phwnd = NULL;
385 return hres;
388 hres = IDispatch_QueryInterface(parent, &IID_IAccessible, (void**)&acc);
389 IDispatch_Release(parent);
390 if(FAILED(hres))
391 return hres;
395 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
396 LPVOID lpvReserved)
398 TRACE("%p, %d, %p\n", hinstDLL, fdwReason, lpvReserved);
400 switch (fdwReason)
402 case DLL_PROCESS_ATTACH:
403 oleacc_handle = hinstDLL;
404 DisableThreadLibraryCalls(hinstDLL);
405 break;
407 return TRUE;
410 HRESULT WINAPI DllRegisterServer(void)
412 TRACE("()\n");
413 return __wine_register_resources(oleacc_handle);
416 HRESULT WINAPI DllUnregisterServer(void)
418 TRACE("()\n");
419 return __wine_unregister_resources(oleacc_handle);
422 void WINAPI GetOleaccVersionInfo(DWORD* pVersion, DWORD* pBuild)
424 *pVersion = MAKELONG(0,7); /* Windows 7 version of oleacc: 7.0.0.0 */
425 *pBuild = MAKELONG(0,0);
428 HANDLE WINAPI GetProcessHandleFromHwnd(HWND hwnd)
430 DWORD proc_id;
432 TRACE("%p\n", hwnd);
434 if(!GetWindowThreadProcessId(hwnd, &proc_id))
435 return NULL;
436 return OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION |
437 PROCESS_VM_READ | PROCESS_VM_WRITE | SYNCHRONIZE, TRUE, proc_id);
440 UINT WINAPI GetRoleTextW(DWORD role, LPWSTR lpRole, UINT rolemax)
442 INT ret;
443 WCHAR *resptr;
445 TRACE("%u %p %u\n", role, lpRole, rolemax);
447 /* return role text length */
448 if(!lpRole)
449 return LoadStringW(oleacc_handle, role, (LPWSTR)&resptr, 0);
451 ret = LoadStringW(oleacc_handle, role, lpRole, rolemax);
452 if(!(ret > 0)){
453 if(rolemax > 0) lpRole[0] = '\0';
454 return 0;
457 return ret;
460 UINT WINAPI GetRoleTextA(DWORD role, LPSTR lpRole, UINT rolemax)
462 UINT length;
463 WCHAR *roletextW;
465 TRACE("%u %p %u\n", role, lpRole, rolemax);
467 if(lpRole && !rolemax)
468 return 0;
470 length = GetRoleTextW(role, NULL, 0);
471 if(!length) {
472 if(lpRole && rolemax)
473 lpRole[0] = 0;
474 return 0;
477 roletextW = HeapAlloc(GetProcessHeap(), 0, (length + 1)*sizeof(WCHAR));
478 if(!roletextW)
479 return 0;
481 GetRoleTextW(role, roletextW, length + 1);
483 length = WideCharToMultiByte( CP_ACP, 0, roletextW, -1, NULL, 0, NULL, NULL );
485 if(!lpRole){
486 HeapFree(GetProcessHeap(), 0, roletextW);
487 return length - 1;
490 if(rolemax < length) {
491 HeapFree(GetProcessHeap(), 0, roletextW);
492 lpRole[0] = 0;
493 return 0;
496 WideCharToMultiByte( CP_ACP, 0, roletextW, -1, lpRole, rolemax, NULL, NULL );
498 if(rolemax < length){
499 lpRole[rolemax-1] = '\0';
500 length = rolemax;
503 HeapFree(GetProcessHeap(), 0, roletextW);
505 return length - 1;
508 UINT WINAPI GetStateTextW(DWORD state_bit, WCHAR *state_str, UINT state_str_len)
510 DWORD state_id;
512 TRACE("%x %p %u\n", state_bit, state_str, state_str_len);
514 if(state_bit & ~(STATE_SYSTEM_VALID | STATE_SYSTEM_HASPOPUP)) {
515 if(state_str && state_str_len)
516 state_str[0] = 0;
517 return 0;
520 state_id = IDS_STATE_NORMAL;
521 while(state_bit) {
522 state_id++;
523 state_bit /= 2;
526 if(state_str) {
527 UINT ret = LoadStringW(oleacc_handle, state_id, state_str, state_str_len);
528 if(!ret && state_str_len)
529 state_str[0] = 0;
530 return ret;
531 }else {
532 WCHAR *tmp;
533 return LoadStringW(oleacc_handle, state_id, (WCHAR*)&tmp, 0);
538 UINT WINAPI GetStateTextA(DWORD state_bit, CHAR *state_str, UINT state_str_len)
540 DWORD state_id;
542 TRACE("%x %p %u\n", state_bit, state_str, state_str_len);
544 if(state_str && !state_str_len)
545 return 0;
547 if(state_bit & ~(STATE_SYSTEM_VALID | STATE_SYSTEM_HASPOPUP)) {
548 if(state_str && state_str_len)
549 state_str[0] = 0;
550 return 0;
553 state_id = IDS_STATE_NORMAL;
554 while(state_bit) {
555 state_id++;
556 state_bit /= 2;
559 if(state_str) {
560 UINT ret = LoadStringA(oleacc_handle, state_id, state_str, state_str_len);
561 if(!ret && state_str_len)
562 state_str[0] = 0;
563 return ret;
564 }else {
565 CHAR tmp[256];
566 return LoadStringA(oleacc_handle, state_id, tmp, sizeof(tmp));